给你一个整数数组 arr
,每一次操作你都可以选择并删除它的一个 回文 子数组 arr[i], arr[i+1], ..., arr[j]
( i <= j
)。
注意,每当你删除掉一个子数组,右侧元素都会自行向前移动填补空位。
请你计算并返回从数组中删除所有数字所需的最少操作次数。
示例 1:
输入:arr = [1,2] 输出:2
示例 2:
输入:arr = [1,3,4,1,5] 输出:3 解释:先删除 [4],然后删除 [1,3,1],最后再删除 [5]。
提示:
1 <= arr.length <= 100
1 <= arr[i] <= 20
思路:dp
[i][j]:表示删除区间(i,j)所需要的最小操作步骤,这题和区间dp的模板题的唯一区别是每次可以删除一个回文串,我们知道回文串的两端一定是相等的(对称),因此若区间端点相等,我们直接用(i+1,j)递推过来。
class Solution {
public int minimumMoves(int[] arr) {
int n=arr.length;
int[][] dp=new int[n][n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dp[i][j]=1000000;
for(int i=0;i<n;i++) dp[i][i]=1;
for(int len=1;len<n;len++)
for(int i=0;i+len<n;i++) {
int j=i+len;
for(int k=i;k<j;k++)
dp[i][j]=Math.min(dp[i][j], dp[i][k]+dp[k+1][j]);
if(arr[i]==arr[j]) {
if(len==1) dp[i][j]=1;
else dp[i][j]=Math.min(dp[i][j], dp[i+1][j-1]);
}
}
return dp[0][n-1];
}
}