Welcome to Subscribe On Youtube
Formatted question description: https://leetcode.ca/all/1246.html
1246. Palindrome Removal
Level
Hard
Description
Given an integer array arr
, in one move you can select a palindromic subarray arr[i], arr[i+1], ..., arr[j]
where i <= j
, and remove that subarray from the given array. Note that after removing a subarray, the elements on the left and on the right of that subarray move to fill the gap left by the removal.
Return the minimum number of moves needed to remove all numbers from the array.
Example 1:
Input: arr = [1,2]
Output: 2
Example 2:
Input: arr = [1,3,4,1,5]
Output: 3
Explanation: Remove [4] then remove [1,3,1] then remove [5].
Constraints:
1 <= arr.length <= 100
1 <= arr[i] <= 20
Solution
Use dynamic programming. Create a 2D array dp
of arr.length
rows and arr.length
columns, where dp[i][j]
represents the minimum number of moves needed to remove all numbers from arr[i]
to arr[j]
for i <= j
. Initialize dp[i][j] = j - i + 1
for all 0 <= i <= j < arr.length
.
For all 1 <= i < arr.length
, set dp[i - 1][i] = 1
if arr[i - 1] == arr[i]
. Then loop over i
from arr.length - 3
to 1 and loop over j
from i + 2
to arr.length - 1
, and update dp[i][j]
as follows. If arr[i] == arr[j]
, then update dp[i][j] = dp[i + 1][j - 1]
. Also, dp[i][j]
is the minimum possible value of dp[i][k] + dp[k + 1][j]
among all possible values of k
such that i <= k < j
.
Finally, return dp[0][arr.length - 1]
.
-
class Solution { public int minimumMoves(int[] arr) { int length = arr.length; int[][] dp = new int[length][length]; for (int i = 0; i < length; i++) { for (int j = i; j < length; j++) dp[i][j] = j - i + 1; } for (int i = 1; i < length; i++) { if (arr[i - 1] == arr[i]) dp[i - 1][i] = 1; } for (int i = length - 3; i >= 0; i--) { for (int j = i + 2; j < length; j++) { if (arr[i] == arr[j]) dp[i][j] = dp[i + 1][j - 1]; for (int k = i; k < j; k++) dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k + 1][j]); } } return dp[0][length - 1]; } }
-
class Solution { public: int minimumMoves(vector<int>& arr) { int n = arr.size(); int f[n][n]; memset(f, 0, sizeof f); for (int i = 0; i < n; ++i) { f[i][i] = 1; } for (int i = n - 2; i >= 0; --i) { for (int j = i + 1; j < n; ++j) { if (i + 1 == j) { f[i][j] = arr[i] == arr[j] ? 1 : 2; } else { int t = arr[i] == arr[j] ? f[i + 1][j - 1] : 1 << 30; for (int k = i; k < j; ++k) { t = min(t, f[i][k] + f[k + 1][j]); } f[i][j] = t; } } } return f[0][n - 1]; } };
-
class Solution: def minimumMoves(self, arr: List[int]) -> int: n = len(arr) f = [[0] * n for _ in range(n)] for i in range(n): f[i][i] = 1 for i in range(n - 2, -1, -1): for j in range(i + 1, n): if i + 1 == j: f[i][j] = 1 if arr[i] == arr[j] else 2 else: t = f[i + 1][j - 1] if arr[i] == arr[j] else inf for k in range(i, j): t = min(t, f[i][k] + f[k + 1][j]) f[i][j] = t return f[0][n - 1]
-
func minimumMoves(arr []int) int { n := len(arr) f := make([][]int, n) for i := range f { f[i] = make([]int, n) f[i][i] = 1 } for i := n - 2; i >= 0; i-- { for j := i + 1; j < n; j++ { if i+1 == j { f[i][j] = 2 if arr[i] == arr[j] { f[i][j] = 1 } } else { t := 1 << 30 if arr[i] == arr[j] { t = f[i+1][j-1] } for k := i; k < j; k++ { t = min(t, f[i][k]+f[k+1][j]) } f[i][j] = t } } } return f[0][n-1] } func min(a, b int) int { if a < b { return a } return b }