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.
We want to remove the array in the minimum number of moves, where each move removes a palindromic subarray. If the ends of a subarray are equal, we can try to remove them together, possibly reducing the number of moves. This suggests a DP approach on intervals.
classSolution {
public:int minimumMoves(vector<int>& arr) {
int n = arr.size();
vector<vector<int>> dp(n, vector<int>(n, n));
for (int i =0; i < n; ++i) dp[i][i] =1;
for (int len =2; len <= n; ++len) {
for (int i =0; i + len -1< n; ++i) {
int j = i + len -1;
if (arr[i] == arr[j])
dp[i][j] = (len ==2) ?1: dp[i+1][j-1];
for (int k = i; k < j; ++k)
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]);
}
}
return dp[0][n-1];
}
};
classSolution {
publicintminimumMoves(int[] arr) {
int n = arr.length;
int[][] dp =newint[n][n];
for (int i = 0; i < n; i++) Arrays.fill(dp[i], n);
for (int i = 0; i < n; i++) dp[i][i]= 1;
for (int len = 2; len <= n; len++) {
for (int i = 0; i + len - 1 < n; i++) {
int j = i + len - 1;
if (arr[i]== arr[j])
dp[i][j]= (len == 2) ? 1 : 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][n-1];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
classSolution {
funminimumMoves(arr: IntArray): Int {
val n = arr.size
val dp = Array(n) { IntArray(n) { n } }
for (i in0 until n) dp[i][i] = 1for (len in2..n) {
for (i in0..n-len) {
val j = i+len-1if (arr[i] == arr[j])
dp[i][j] = if (len ==2) 1else dp[i+1][j-1]
for (k in i until j)
dp[i][j] = minOf(dp[i][j], dp[i][k] + dp[k+1][j])
}
}
return dp[0][n-1]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
classSolution:
defminimumMoves(self, arr: list[int]) -> int:
n = len(arr)
dp = [[n] * n for _ in range(n)]
for i in range(n):
dp[i][i] =1for l in range(2, n+1):
for i in range(n-l+1):
j = i+l-1if arr[i] == arr[j]:
dp[i][j] =1if l ==2else dp[i+1][j-1]
for k in range(i, j):
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j])
return dp[0][n-1]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
impl Solution {
pubfnminimum_moves(arr: Vec<i32>) -> i32 {
let n = arr.len();
letmut dp =vec![vec![n asi32; n]; n];
for i in0..n { dp[i][i] =1; }
for len in2..=n {
for i in0..=n-len {
let j = i+len-1;
if arr[i] == arr[j] {
dp[i][j] =if len ==2 { 1 } else { dp[i+1][j-1] };
}
for k in i..j {
dp[i][j] = dp[i][j].min(dp[i][k] + dp[k+1][j]);
}
}
}
dp[0][n-1]
}
}