LeetCode:构造有效字符串的最少插入数

地址:. - 力扣(LeetCode)
题目描述:给你一个字符串 word ,你可以向其中任何位置插入 “a”、“b” 或 “c” 任意次,返回使 word 有效 需要插入的最少字母数。
如果字符串可以由 “abc” 串联多次得到,则认为该字符串 有效

提示:

  • 1 <= word.length <= 50
  • word 仅由字母 “a”、“b” 和 “c” 组成。

题解

动态规划

d[i]表示前i个字符拼凑成若干个 abc所需要的最小插入数
d[0] = 0
如果word[i] 单独存在于一组 abc中,d[i]=d[i−1]+2
那怎么知道word[i]是不是单独存在一组abc中呢?

首先 我们能知道的是c>b>a
如果word[i]>word[i−1] 那就能肯定是在同一组abc中的
比如字符串ab,b>a 我们能肯定它们是在同一组abc中的
比如字符串ac,c>a 我们能肯定它们是在同一组abc中的
比如字符串bc,c>b 我们能肯定它们是在同一组abc中的

除了上述情况之外,其他的情况word[i]都是单独成一组的
比如ca,a 既然是单独成一组,就需要再插入两个元素构成一组 所以d[i]=d[i−1]+2

如果 word[i]>word[i−1],那么 word[i]可以和 word[i−1] 在同一组 abc 中,d[i]=d[i−1]−1
这种情况就是word[i]跟前面可以成一组,但是我们要知道的是在word[i]插入进word[0]-word[i-1]之前,我们通过动态规划,已经计算好了word[0]-word[i-1]这个字符串拼凑成若干个 abc所需要的最小插入数
那就是可以理解为,这个时候,word[0]-word[i-1]的最后三位字符串已经成组成abc了
这个时候我们把word[i]添加进去成组,也就意味着d[i-1],也就是word[0]-word[i-1]这个字符串拼凑成若干个 abc所需要的最小插入数需要减1,因为word[i]替换占位了,相应的插入数就要减少了,所以d[i]=d[i−1]−1

通过一个例子加深理解:
word=aacabc
答案应该是:3 a(bc)a(b)cabc

第一步:求d[1],因为a前面是空字符,所以字符串a肯定是自成一组的,d[1] = d[0]+2 = 2
LeetCode:构造有效字符串的最少插入数_第1张图片

第二步:求d[2],因为a前面是a,所以字符串word[1]:a自成一组的,d[2] = d[1]+2 = 4
LeetCode:构造有效字符串的最少插入数_第2张图片

第三步:求d[3],因为c前面是a,所以字符串word[2]:c跟前面的word[1]:a是同一组的,d[3] = d[2]-1 = 3
LeetCode:构造有效字符串的最少插入数_第3张图片

第四步:求d[4],因为a前面是c,所以字符串word[3]:a自成一组,d[4] = d[3]+2 = 5
LeetCode:构造有效字符串的最少插入数_第4张图片

第五步:求d[5],因为b前面是a,所以字符串word[4]:b跟前面的word[3]:a是同一组的,d[5] = d[4]-1 = 4
LeetCode:构造有效字符串的最少插入数_第5张图片

第六步:求d[6],因为c前面是b,所以字符串word[5]:c跟前面的word[4]:b是同一组的,d[6] = d[5]-1 = 3
LeetCode:构造有效字符串的最少插入数_第6张图片

所以答案就是d[6] = 3

代码实现
/**
 * @param {string} word
 * @return {number}
 */
var addMinimum = function(word) {
   const n = word.length
   const d = new Array(n+1).fill(0)
   for(let i=1;i<=n;i++){
       d[i] = d[i-1]+2
       if(i>1&&word[i-1]>word[i-2]){
            d[i] = d[i-1]-1
       }
   }
   
   return d[n]
};

状态转移时,最多只会依赖前一个状态 d[i−1],因此使用滚动数组优化可以使得空间复杂度降至 O(1)

/**
 * @param {string} word
 * @return {number}
 */
var addMinimum = function(word) {
   const n = word.length
   let d = 0
   for(let i=1;i<=n;i++){
       d+=2
       if(i>1&&word[i-1]>word[i-2]){

           // d = (d-2)-1  d-2是为了还原状态 因为前面+2了
           d-=3
       }
   }
   
   return d
};

你可能感兴趣的:(#,LeetCode,leetcode,算法)