1. 題目
給你一個整數數組 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
來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/palindrome-removal
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
2. 解題
dp[i][j]
表示區間[i,j]
的最少移除次數- 如果已知
dp[i][j]
,推導dp[i-1][j+1]
- 如果兩側相等
arr[i-1] == arr[j+1]
,dp[i-1][j+1] = min(dp[i-1][j+1], dp[i][j])
- 對區間而言,把區間分成任意的兩份,求和取最小
對所有可能的 k,dp[i-1][j+1] = min(dp[i-1][j+1], dp[i-1][k]+dp[k+1][j+1])
class Solution {
public:
int minimumMoves(vector<int>& arr) {
int n = arr.size(), i, j,k, len;
vector<vector<int>> dp(n, vector<int>(n,INT_MAX));
for(i = 0; i < n; ++i)
{
dp[i][i] = 1;//初始化
if(i < n-1 && arr[i]==arr[i+1])
dp[i][i+1] = 1;
else if(i < n-1 && arr[i]!=arr[i+1])
dp[i][i+1] = 2;
}
for(len = 0; len < n; ++len)
{ //按長度遍歷
for(i = 0; i < n; ++i)
{
j = i+len;//右端點
if(j >= n || dp[i][j]==INT_MAX) continue;
if(i-1 >=0 && j+1 < n)
{
for(k = i-1; k <= j; ++k)
dp[i-1][j+1] = min(dp[i-1][j+1], dp[i-1][k]+dp[k+1][j+1]);
if(arr[i-1] == arr[j+1])
dp[i-1][j+1] = min(dp[i-1][j+1], dp[i][j]);
}
}
}
return dp[0][n-1];
}
};
440 ms 12.9 MB
我的CSDN博客地址 https://michael.blog.csdn.net/
長按或掃碼關注我的公衆號(Michael阿明),一起加油、一起學習進步!