【力扣】2645. 构造有效字符串的最小插入数(动态规划 贪心 滚动数组优化 C++ Go)

简介: 【2月更文挑战第17天】2645. 构造有效字符串的最小插入数(动态规划 贪心 滚动数组优化 C++ Go)

题目链接

题意

给你一个字符串 word ,你可以向其中任何位置插入 "a"、"b" 或 "c" 任意次,返回使 word 有效 需要插入的最少字母数。
如果字符串可以由 "abc" 串联多次得到,则认为该字符串 有效 。
提示:
$1 <= word.length <= 50$
$word$ 仅由字母 "a"、"b" 和 "c" 组成。

思路

dp[i]表示前i个字符构成有效字符串的最小插入数,下标从1开始

  • 初始化为dp[0]=0表示前0个字符构成有效字符串最小需要插入0个字符
  • 最终答案为dp[len(word)]
  • 转移过程:
    • i个字符单独属于一个abc里,需要插入的字符数就是2,转移方程为dp[i]=dp[i-1]+2
    • 如果第i个字符可以跟第i-1个字符属于一个abc,也就是满足word[i]>word[i-1],需要插入的字符数就是-1,即前面可以少插入一个字符,转移方程为dp[i] = min(dp[i], dp[i-1]-1)
  • 贪心的考虑,每个字符都优先跟前面的字符去组合,而且dp[i-1]+2<dp[i-1]-1,所以第二个转移方程可以写为dp[i]=dp[i-1]-1
  • 上述做法的时间复杂度为$O(n)$,空间复杂度也是$O(n)$。
  • 观察代码发现其实状态转移的时候只依赖上一个状态,所以可以使用滚动数组进行优化,优化后的空间复杂度为$O(1)$

    代码

    普通版本golang代码

    func addMinimum(word string) int {
         
      //dp[i]表示前i个字符构成有效字符串的最小插入数
      dp := make([]int, len(word)+2)
      for i := 1; i <= len(word); i++ {
         
          dp[i] = dp[i-1] + 2
          if i > 1 && word[i-1] > word[i-2] {
         
              dp[i] = dp[i-1] - 1
              //dp[i] = min(dp[i], dp[i-1]-1)
          }
      }
      return dp[len(word)]
    }
    

    普通版本c++代码

class Solution {
   
public:
    int addMinimum(string word) {
   
        int n = word.size();
        int dp[n+1];
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++){
   
            dp[i] = dp[i-1]+2;
            if(i>1&&word[i-1]>word[i-2]){
   
                dp[i] = dp[i-1]-1;
            }
        }
        return dp[n];
    }
};

滚动数组版本golang代码

func addMinimum(word string) int {
   
    ans, las := 0, 0
    for i := 1; i <= len(word); i++ {
   
        ans = las + 2
        if i > 1 && word[i-1] > word[i-2] {
   
            ans = las - 1
        }
        las = ans
    }
    return ans
}

滚动数组版本c++代码

class Solution {
   
    public:
        int addMinimum(string word) {
   
            int ans=0;
            int las= 0;
            for (int i = 1; i <= word.size(); i++) {
   
                ans = las + 2;
                if (i > 1 && word[i-1] > word[i-2]) {
   
                    ans = las - 1;
                }
                las = ans;
            }
            return ans;
        }
};
目录
相关文章
|
1月前
|
存储 C++
使用C++代码实现哈夫曼树的构造
使用C++代码实现哈夫曼树的构造
|
1月前
|
算法
【数组相关面试题】LeetCode试题
【数组相关面试题】LeetCode试题
|
17天前
|
算法 Java C语言
C++和Java中的随机函数你玩明白了吗?内附LeetCode470.rand7()爆改rand10()巨详细题解,带你打败LeetCode%99选手
C++和Java中的随机函数你玩明白了吗?内附LeetCode470.rand7()爆改rand10()巨详细题解,带你打败LeetCode%99选手
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
|
12天前
|
C++
【力扣】2562. 找出数组的串联值
【力扣】2562. 找出数组的串联值
|
1月前
|
存储 并行计算 算法
C++动态规划的全面解析:从原理到实践
C++动态规划的全面解析:从原理到实践
95 0
|
1月前
|
存储 算法
《LeetCode 热题 HOT 100》——寻找两个正序数组的中位数
《LeetCode 热题 HOT 100》——寻找两个正序数组的中位数
|
1月前
|
存储
leetcode2744. 最大字符串配对数目
leetcode2744. 最大字符串配对数目
17 0
|
1月前
|
机器学习/深度学习 NoSQL Shell
力扣刷题-翻转字符串
力扣刷题-翻转字符串
12 1
|
1月前
|
存储
力扣刷题-最大子数组和
力扣刷题-最大子数组和
10 1