↓快轉到主要內容
  1. LeetCode/

LeetCode 1246: Palindrome Removal

·1 分鐘· ·
LeetCode Hard Dynamic-Programming Interval-Dp Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-09-12

  • 提交紀錄:Accepted(一次通過)

解題思路
#

dp[i][j] = 把 arr[i..j] 全部刪掉的最少次數。三種情況:

  1. arr[i] 自己刪:1 + dp[i + 1][j]。
  2. 兩端相同(arr[i] == arr[j]):先把中間刪到剩一個回文,最後一次連同兩端一起刪,次數跟只刪中間一樣:dp[i + 1][j - 1](中間是空的時候是 1)。
  3. 切成兩段:dp[i][k] + dp[k + 1][j]。

依長度由短到長填表。

我的解法
#

class Solution:
    def minimumMoves(self, arr: List[int]) -> int:
        n = len(arr)
        dp = [[0] * n for _ in range(n)]           # dp[i][j]:刪完 arr[i..j] 的最少次數
        for i in range(n):
            dp[i][i] = 1
        for length in range(2, n + 1):
            for i in range(n - length + 1):
                j = i + length - 1
                dp[i][j] = 1 + dp[i + 1][j]        # arr[i] 自己刪
                if arr[i] == arr[j]:               # 兩端跟中間最後一次一起刪
                    dp[i][j] = min(dp[i][j], dp[i + 1][j - 1] if length > 2 else 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]

複雜度
#

時間 O(n^3),n <= 100。空間 O(n^2)。

要特別避免的錯誤
#

  • 兩端相同時,次數是 dp[i + 1][j - 1],不用再加 1:兩端可以搭中間最後一次刪除的順風車。
  • 長度 2 的時候中間是空的,次數是 1。

面試口說整理
#

dp[i][j] 是刪完這段的最少次數。左端可以自己刪;如果兩端相同,就先把中間刪到剩一個回文,最後一次連兩端一起刪,次數跟中間一樣;或者在某個位置切成兩段分開刪。三種取最小,依長度由短到長填表,時間 O(n^3)。

相關文章

LeetCode 1335: Minimum Difficulty of a Job Schedule
·1 分鐘
LeetCode Hard Dynamic-Programming Interval-Dp Array
LeetCode 1335 解題筆記:切成 d 段的分割 DP;dp(i, k) = 從第 i 個工作開始、剩 k 天的最小難度,枚舉今天做到哪裡,邊枚舉邊更新今天的最大難度
LeetCode 312: Burst Balloons
·1 分鐘
LeetCode Hard Dynamic-Programming Interval-Dp Array
LeetCode 312 解題筆記:枚舉區間 (i, j) 裡「最後一個」戳破的氣球 k,這時它的鄰居就是 i 和 j,左右兩邊的子問題互相獨立
LeetCode 2163: Minimum Difference in Sums After Removal of Elements
·2 分鐘
LeetCode Hard Dynamic-Programming Heap Array
LeetCode 2163 解題筆記:枚舉第一段和第二段的分界 k;左邊 nums[:k] 選 n 個最小的(最大堆維護),右邊 nums[k:] 選 n 個最大的(最小堆維護),前後綴各掃一次
LeetCode 4041: Minimum Operations to Form Subset Sum II
·2 分鐘
LeetCode Hard Dynamic-Programming Knapsack Breadth-First-Search Array
LeetCode 4041 解題筆記:乘除可以任意順序,用 BFS 找每個數能變成的所有值(不超過 sum)和最少步數,再做跟 4040 一樣的分組 0/1 背包
LeetCode 2585: Number of Ways to Earn Points
·1 分鐘
LeetCode Hard Dynamic-Programming Knapsack Array
LeetCode 2585 解題筆記:有數量上限的背包(分組背包);每種題目選 0 到 count 題,容量倒著走,在裡面枚舉選幾題
LeetCode 410: Split Array Largest Sum
·1 分鐘
LeetCode Hard Dynamic-Programming Binary-Search Greedy Prefix-Sum Array
LeetCode 410 解題筆記:對答案二分搜尋;給定上限 mid,貪心地能塞就塞,數出最少要切幾段,段數 <= k 就表示 mid 可行