持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情
每日力扣是一个专门用来讲力扣中国每天发布的每日一题的栏目。本专栏不提供题目的解答源码,只讲解思路,目的是养成每日刷题、提高自己手感,从而达到算法熟练的目标。
题目(已做删减处理)
给定一个字符串
s,计算s的 不同非空子序列 的个数。因为结果可能很大,所以返回答案需要对 ****10^9 + 7取余 。字符串的 子序列 是经由原字符串删除一些(也可能不删除)字符但不改变剩余字符相对位置的一个新字符串。
分析
一道很常见的动态规划题目。如果我们将 dp[i]表示为i个字符可以组成的不同的子序列,那么我们可以很容易的得出以下的表达式:
- dp[i] = dp[i-1]+new-repeat
其中,new 为dp[i-1]在新增1个字符后,新增的子序列个数,repeat为新增后又重复的子序列个数。因此,我们接下来主要关于new 和 repeat 的取值规则。 - new
首先是new。其实这个很好计算,其实本质上来说,它就是dp[i-1]。 - repeat
我们观察下面一张图,当遍历到第二个a的时候,出现重复的序列是 a、ab,它对应的,其实是步骤2中新增的两个序列。因此我们可以用一个临时数组来记录上一次字符新增的个数。
上述的所有步骤中,都不考虑空字符串,因此在最后的返回数据时候,我们要-1,保证数据的准确性。
总结
一道很经典的动态规划的题目。但是和之前我们遇到的动态规划题目有点不同的是,这道题目在进行判断的时候,还是增加了一些难度的。不像是之前,只要你有一定的动态规划知识,就能够套用公式似的解答。
这道题目并不要求算法新人们能够完全掌握,如果看到题目20分钟内各种尝试都没有得到正确的答案,不如光明正大的在讨论区查看别人的优秀解答思路。然后整理一下,能够消化成自己的思想,不看代码完成解答。
总的来说,这的确是一道很不错的动态规划题目,值得所有人学习并且思考里面的解题思路。