【力扣】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++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略
【C++篇】C++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略
46 2
|
1月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化2
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
60 6
|
1月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化1
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
52 7
|
2月前
|
Go
Go字节数组与字符串相互转换
Go字节数组与字符串相互转换
36 3
|
1月前
【LeetCode 37】106.从中序与后序遍历构造二叉树
【LeetCode 37】106.从中序与后序遍历构造二叉树
14 0
|
2月前
|
存储 Go
go语言字符串变小写
go语言字符串变小写
|
3月前
|
Python
【Leetcode刷题Python】105. 从前序与中序遍历序列构造二叉树
LeetCode上105号问题"从前序与中序遍历序列构造二叉树"的Python实现,通过递归方法根据前序和中序遍历序列重建二叉树。
25 3
|
3月前
|
Go 开发者
|
3月前
|
JSON Go 数据格式
Go实现json字符串与各类struct相互转换
文章通过Go语言示例代码详细演示了如何实现JSON字符串与各类struct之间的相互转换,包括结构体对象生成JSON字符串和JSON字符串映射到struct对象的过程。
30 0
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行