題目描述:給定兩個字串 word1 和 word2,請計算將 word1 轉換為 word2 所需的最少操作次數。允許的操作有三種:插入一個字元、刪除一個字元、替換一個字元。
解題思路:
這是經典的二維動態規劃問題,稱為 Levenshtein Distance(列文斯坦距離)。
定義 dp[i][j] 為將 word1[0..i-1] 轉換為 word2[0..j-1] 所需的最少操作數。
狀態轉移:
word1[i-1] == word2[j-1]:當前字元相同,不需要操作,dp[i][j] = dp[i-1][j-1]word1[i-1],dp[i-1][j] + 1word1 末尾插入 word2[j-1],dp[i][j-1] + 1word1[i-1] 替換為 word2[j-1],dp[i-1][j-1] + 1邊界條件:
dp[i][0] = i:將長度為 i 的字串轉換為空字串,需要 i 次刪除dp[0][j] = j:將空字串轉換為長度為 j 的字串,需要 j 次插入空間優化:因為 dp[i][j] 只依賴上一列的值,可以用滾動陣列將空間壓縮至 O(n),僅需保存前一列以及當前計算所需的 dp[i-1][j-1](以 prev 變數存儲)。
時間複雜度:O(m·n) — 雙層迴圈分別遍歷 word1(長度 m)與 word2(長度 n),每個格子計算為 O(1)。
空間複雜度:O(n) — 使用滾動陣列優化,僅維護一列大小為 n+1 的 dp 陣列,以及一個 prev 變數來記錄左上角的值,省去原本 O(m·n) 的二維空間。
1. Initialize dp[0..n] where dp[j] = j (base case: empty word1 to word2[0..j-1])
2. For each i from 1 to m (iterate over word1):
a. Save prev = dp[0], then set dp[0] = i (base case: word1[0..i-1] to empty word2)
b. For each j from 1 to n (iterate over word2):
- Save temp = dp[j] (this is dp[i-1][j])
- If word1[i-1] == word2[j-1]: dp[j] = prev (no operation needed)
- Else: dp[j] = 1 + min(prev, dp[j], dp[j-1]) (replace, delete, insert)
- Update prev = temp
3. Return dp[n]遞迴 + 記憶化搜索 O(m·n):從 (m, n) 往下遞迴,每次根據字元是否相同選擇不同操作,用 memo[i][j] 儲存已計算的子問題結果,避免重複計算。思路直觀但呼叫堆疊深度最深為 O(m+n),不如迭代 DP 穩定。
二維 DP(標準版)O(m·n) 時間,O(m·n) 空間:直接建立 (m+1)×(n+1) 的二維表格,逐格填入,程式碼最清晰易懂,適合初學者理解狀態轉移邏輯,空間換可讀性。
word1 到 word2 的具體操作序列?