LeetCode 115 Distinct Subsequences (DP)
这里通过 LeetCode 中的一道动态规划题目(115. Distinct Subsequences)来复习一下动态规划中的正反向递推和滚动数组的使用。
题意:输出字符串 S 中等于字符串 T 的子序列的个数。
分析:这是一道比较典型的动态规划题目,考虑状态:
dp[i][j] 表示字符串 s[:i] 中等于子序列 t[:j] 的个数
其中 s[:i] 表示字符串 S 的前 i 个字符构成的子串,t[:j] 表示字符串 T 的前 j 个字符构成的子串。那么有初始状态 dp[0][0] = 1
首先 dp[i][j] 肯定可以由 dp[i-1][j] 转移,因为 s[:i-1] 的子序列肯定是 s[i] 的子序列;特别地,若 s[i-1] == t[j-1],dp[i][j] 还可以由 dp[i-1][j-1] 转移。
那么不难写出逆向递推的方案:
1 | def numDistinct(self, s: str, t: str) -> int: |
还有正向递推的方案:
1 | def numDistinct(self, s: str, t: str) -> int: |
考虑到 dp[i][j] 只依赖 dp[i-1][j-1] 和 dp[i-1]][j],实际上没必要使用二维数组来存储状态。利用滚动数组的性质,只使用一维数组就可以。 j 从后往前递推时,可以让 dp[j] 在第 i 次循环中表示 dp[i][j],而 dp[j-1] 则表示 dp[i-1][j-1],如下:
1 | def numDistinct(self, s: str, t: str) -> int: |
Leetcode 115. Distinct Subsequences
Given a string S and a string T, count the number of distinct subsequences of S which equals T.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).
Example 1:
1 | Input: S = "rabbbit", T = "rabbit" |
Example 2:
1 | Input: S = "babgbag", T = "bag" |