1143.Longest Common Subsequence

25 年 8 月 21 日 星期四
443 字
3 分钟

1143. Longest Common Subsequence

从右往左递归,方便1:1翻译成从左往右的递推

[[0] _ (m+1) for _ in range((n+1))] 和 [[0] _ (m+1)] * (n+1) 的区别

好问题 👍 这两个看起来很像,但差别非常大。我们逐个分析:


1. 写法一:列表推导式

python
f = [[0] * (m+1) for _ in range(n+1)]
  • 每次循环都会新建一个 独立的列表
  • 所以总共有 n+1 个不同的子列表。
  • 修改某一行不会影响到其他行。

✅ 这是我们真正想要的二维数组(矩阵)。

例子:

python
m, n = 2, 2
f = [[0] * (m+1) for _ in range(n+1)]
f[0][0] = 1
print(f)

输出:

text
[[1, 0, 0],
 [0, 0, 0],
 [0, 0, 0]]

2. 写法二:列表乘法

python
f = [[0] * (m+1)] * (n+1)
  • 外层其实是把 同一个子列表的引用复制了 n+1 次
  • 所以所有行都指向同一个对象。
  • 改动一行,其他行也会同时变。

❌ 这通常是 bug。

例子:

python
m, n = 2, 2
f = [[0] * (m+1)] * (n+1)
f[0][0] = 1
print(f)

输出:

text
[[1, 0, 0],
 [1, 0, 0],
 [1, 0, 0]]

可以看到,本来只改 f[0][0],结果三行的第一列都变了。


✅ 总结

  • [[0] * (m+1) for _ in range(n+1)] → 正确二维矩阵,行之间独立。
  • [[0] * (m+1)] * (n+1) → 每行其实是同一个列表的别名,修改会联动,容易出 bug。
python
#
# @lc app=leetcode.cn id=1143 lang=python3
#
# [1143] 最长公共子序列
#

# @lc code=start
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        n = len(text1)
        m = len(text2)
        # @cache
        # def dfs(i, j):
        #     if i < 0 or j < 0:
        #         return 0
        #     if text1[i] == text2[j]:
        #         return dfs(i-1, j-1) + 1
        #     return max(dfs(i-1, j), dfs(i, j-1))
        # return dfs(n-1, m-1)

        f = [[0] * (m+1) for _ in range((2))]
        for i, x in enumerate(text1):
            for j, y in enumerate(text2):
                if x == y:
                    f[(i+1)%2][j+1] = f[i%2][j] + 1
                else:
                    f[(i+1)%2][j+1] = max(f[i%2][j+1], f[(i+1)%2][j])
        return f[n%2][m]

# @lc code=end

文章标题:1143.Longest Common Subsequence

文章作者:Sirui Chen

文章链接:https://blog.siruichen.me/posts/1143longest_common_subsequence[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。