题目链接
题意
给你一个字符串 word ,你可以向其中任何位置插入 “a”、“b” 或 “c” 任意次,返回使 word 有效 需要插入的最少字母数。
如果字符串可以由 “abc” 串联多次得到,则认为该字符串 有效 。
提示:
1
<
=
w
o
r
d
.
l
e
n
g
t
h
<
=
50
1 <= word.length <= 50
1<=word.length<=50
w
o
r
d
word
word 仅由字母 “a”、“b” 和 “c” 组成。文章来源:https://www.toymoban.com/news/detail-793644.html
思路
dp[i]
表示前i
个字符构成有效字符串的最小插入数,下标从1
开始文章来源地址https://www.toymoban.com/news/detail-793644.html
- 初始化为
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(n),空间复杂度也是 O ( n ) O(n) O(n)。
- 观察代码发现其实状态转移的时候只依赖上一个状态,所以可以使用滚动数组进行优化,优化后的空间复杂度为 O ( 1 ) O(1) 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;
}
};
到了这里,关于【力扣·每日一题】2645. 构造有效字符串的最小插入数(动态规划 贪心 滚动数组优化 C++ Go)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!