LeetCode 115.不同的子序列

LeetCode 115.不同的子序列

详细题目

题目分析

题目大致意思就是在主串中找不同子串的数量。思路比较明显是动态规划。
d p ( i , j ) dp(i, j) dp(i,j)表示 S [ i : ] S[i: ] S[i:] T [ j : ] T[j: ] T[j:]出现的次数(S为主串,T为匹配串)。则递推式有:

d p ( i , j ) = { d p ( i + 1 , j ) , if S[i] == T[j] d p ( i + 1 , j + 1 ) + d p ( i + 1 , j ) , if S[i] != T[j] dp(i,j) = \begin{cases} dp(i + 1, j), & \text{if S[i] == T[j]} \\ dp(i + 1,j + 1) + dp(i + 1, j), & \text{if S[i] != T[j]} \end{cases} dp(i,j)={dp(i+1,j),dp(i+1,j+1)+dp(i+1,j),if S[i] == T[j]if S[i] != T[j]
结束条件: d p ( i , j ) = { 1 , if j >= len(T) 0 , if i >= len(S) dp(i,j) = \begin{cases} 1, & \text{if j >= len(T)} \\ 0, & \text{if i >= len(S)} \end{cases} dp(i,j)={1,0,if j >= len(T)if i >= len(S)
(注意结束条件的顺序)
原问题即dp(0,0),动态规划的实现,笔者用相对容易理解的递归实现(注意记忆化)的,当然也可以用扫描数组的形式去实现。

代码

class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        global d
        d = [[-1 for _ in range(len(t))] for _ in range(len(s))]
        def dp(i, j):
            if j >= len(t):
                return 1
            if i >= len(s):
                return 0
            if d[i][j] != -1:
                return d[i][j]
            
            if s[i] == t[j]:
                ret = dp(i + 1, j + 1) + dp(i + 1, j)
            else:
                ret = dp(i + 1, j)
            
            d[i][j] = ret
            return ret
        
        return dp(0, 0)

吐槽

LeetCode上的某些题解非要把动态规划的两种形式分开来写,还说成是分治。啧啧啧

你可能感兴趣的:(LeetCode,刷题)