X兴员工爆料:C9科班硕在中兴15年了,现在是5a,月薪是21k,正在接受领导全方位否定
算法题:不同的子序列
举个栗子
输入: s = "rabbbit", t = "rabbit"
输出:3
为什么是3呢?因为rabbbit有 3 种方式删出rabbit:第1个 b和后面的it;第2个 b和后面的it;第3个 b和后面的it。
动态规划(Dynamic Programming)救场
dp,其中:dp[i][j]表示用 s[0:i] 的前缀字符串匹配 t[0:j] 的前缀字符串的方案数。
转移方程
如果 **s[i-1] == t[j-1]**:
可以选择匹配:方案数是 dp[i-1][j-1];也可以不匹配:方案数是 dp[i-1][j]。总数: dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
那就只能跳过当前的 **s[i-1]**,即 dp[i][j] = dp[i-1][j]。
边界条件 🚀
dp[i][0] = 1,因为 t 是空字符串,空字符串是任何字符串的子序列;dp[0][j] = 0(当 j > 0),因为空的 s 无法匹配非空的 t。
上代码
def numDistinct(s: str, t: str) -> int:
m, n = len(s), len(t)# 创建 DP 数组,初始化为 0
dp = [[0] * (n + 1) for _ in range(m + 1)]# 初始化边界条件
for i in range(m + 1):
dp[i][0] = 1 # 空的 t 是任何 s 的子序列# 填 DP 表
for i in range(1, m + 1):
for j in range(1, n + 1):
if s[i - 1] == t[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]
else:
dp[i][j] = dp[i - 1][j]return dp[m][n]
# 测试
print(numDistinct("rabbbit", "rabbit")) # 输出:3
核心思路
优化:空间压缩 🛠️
def numDistinct(s: str, t: str) -> int:
m, n = len(s), len(t)
prev = [0] * (n + 1)
curr = [0] * (n + 1)prev[0] = 1 # 空的 t 是任何 s 的子序列
for i in range(1, m + 1):
curr[0] = 1
for j in range(1, n + 1):
if s[i - 1] == t[j - 1]:
curr[j] = prev[j - 1] + prev[j]
else:
curr[j] = prev[j]
prev, curr = curr, [0] * (n + 1)return prev[n]
print(numDistinct("rabbbit", "rabbit")) # 输出:3
对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》。