持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【LeetCode 115. 不同的子序列 】- JavaScript(动态规划)
题目描述
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。
字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)
题目数据保证答案符合 32 位带符号整数范围。
示例 1:
输入:s = "rabbbit", t = "rabbit" 输出:3 解释: 如下图所示, 有 3 种可以从 s 中得到 "rabbit" 的方案。 rabbbit rabbbit rabbbit
动态规划
思路分析:
整体的的思路:分析完题目就知道这又是一个动态规划的题目,这种字符串,子序列的问题,肯定是上来就想DP怎么解,如果DFS 肯定是超时的解法,不过可以从DFS的过程中总结自己DP的状态方程。真的是我的噩梦啊,但是还是得做,呜呜呜。构建dp数组,
dp[i][j]表示t的前i个序列在s的前j个序列出现的次数,为了方便第一行和第一列容易操作,增加了空字符对应的数据,那么可以总结出规律:
- 当前结束位字符相同,可以组合出新的子串:
dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1];- 当前结束位不相同,那么子串数量就是前一个值:
dp[i][j] = dp[i][j - 1];对于上述的状态方程的理解如下
- 当s[j]==t[i]时,
dp[i][j]表示s前j个匹配前i个元素的个数- 所以
dp[i][j]包含两部分,之前匹配的-dp[i-1][j] + 新增的-s[j]匹配t[i]- 可以看出新增的个数就等于
dp[i-1][j-1]也就是匹配t前i-1个元素的个数
var numDistinct = function (s, t) {
const m = s.length, n = t.length;
if (m < n) {
return 0;
}
const dp = new Array(n + 1).fill(0).map(() => new Array(m + 1).fill(0));
for (let i = 0; i <= m; i++) {
dp[0][i] = 1;
}
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
if (t[i - 1] === s[j - 1]) {
dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1];
} else {
dp[i][j] = dp[i][j - 1];
}
}
}
return dp[n][m];
};
思考
注意点:虽然我很菜,做题就像个弟弟,但我的个人也做过很多个串的题,虽然我不一定能推出来,但是我能猜出来动态方程。不是
dp[i-1][j-1]就是dp[i-1][j]这类的,不知道这是好是坏呢
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤