2024.1.11力扣每日一题——构造有效字符串的最少插入数

2024.1.11

      • 题目来源
      • 我的题解
        • [方法一 暴力模拟](#方法一 暴力模拟)
        • [方法二 动态规划](#方法二 动态规划)
        • [方法三 直接拼接](#方法三 直接拼接)
        • [方法四 计算组数](#方法四 计算组数)

题目来源

力扣每日一题;题序:2645

我的题解

方法一 暴力模拟

直接模拟,根据题意可知 若是abc则不用插入,若是ab,ac,bc这需要 插入一个字符,其他的则需要插入两个字符。因此使用String的替换功能,先将word中的所有abc替换成 _ ,然后再分别将ab,ac,bc从左到右替换成 _ ,最后统计剩下的字符中 a b c的数量
时间复杂度 :O( n 2 n^2 n2) n是字符串的长度。除了遍历的O(n),还有替换方法内部的O(n)
空间复杂度:O(1)

java 复制代码
public int addMinimum(String word) {
   word=word.replaceAll("abc","_");
    int n=word.length();
    if(n==0)
        return 0;
    int res=0;
    while(word.contains("ab")){
        res++;
        word=word.replaceFirst("ab","_");
    }
    while(word.contains("bc")){
        res++;
        word=word.replaceFirst("bc","_");
    }
    while(word.contains("ac")){
        res++;
        word=word.replaceFirst("ac","_");
    }
    for(int i=0;i<word.length();i++){
        char ch=word.charAt(i);
        if(ch>='a'&&ch<='c'){
            res+=2;
        }
    }
    return res;
}
方法二 动态规划

定义dp[i]状态表示前i个字符凑成若干个abc所需插入的字符数,则转移过程:

  • 若第i个字符单独在一组abc中,则dp[i]=dp[i-1]+2
  • 若word[i]>word[i-1]则表示word[i]和word[i-1]在一组abc中,则dp[i]=dp[i-1]-1
    时间复杂度:O(n)

空间复杂度:O(n)

java 复制代码
public int addMinimum(String word) {
  int n=word.length();
  int[] dp=new int[n+1];
   for(int i=0;i<n;i++){
       dp[i+1]=dp[i]+2;
       if(i<n-1&&word.charAt(i+1)>word.charAt(i)){
           dp[i+1]=dp[i]-1;
       }
   }
   return dp[n];
}

当然,可以发现转移至于i-1状态有关,所以可以使用滚动数组优化空间

java 复制代码
public int addMinimum(String word) {
    int n=word.length();
    int dp_0=0;
    int dp_1=0;
    for(int i=0;i<n;i++){
        dp_1=dp_0+2;
        if(i<n-1&&word.charAt(i+1)>word.charAt(i)){
            dp_1=dp_0-1;
        }
        dp_0=dp_1;
    }
    return dp_1;
}
方法三 直接拼接

参考:官方题解

当前字符小于等于前面字符说明它们一定不在同一组 abc 中,只需要添置若干字符过渡这两者即可。例如 b前面是 c,则需要在中间添置 a,又例如 b 前面是 b,则需要在中间添置 ca。

以上两种情况可以用一个模型来表示,设当前字符是 x,前面字符是 y,那么需要添置的字符个数为 (x−y−1+3)mod  3。其中 +3 再对 3取模,可以应对 x 小于等于 y 的情况。

最后还需要处理头尾两个字符,word[0] 前面添置 word[0]−'a′ 个字符,word[n−1]后面添置 'c′−word[n−1]个字符。两个可以合并为 word[0]−word[n−1]+2
时间复杂度:O(n)

空间复杂度:O(1)

java 复制代码
 public int addMinimum(String word) {
   int n=word.length();
    int res=0;
    if(n==1)
        return 2;
    res+=word.charAt(0)-word.charAt(n-1)+2;
    for(int i=0;i<n-1;i++){
        int count=word.charAt(i+1)-word.charAt(i)-1+3;
        res+=count%3;
    }
    return res;
  
}
方法四 计算组数

计算递增序列的组------也就是每一个递增序列都是一个组,然后使用一个变量count记录当前递增序列的长度,需要插入的字符数=3-count。在不满足递增的时候才会计算需要插入的字符数,并且重置count。
时间复杂度:O(n)。n是word的长度

空间复杂度:O(1)

java 复制代码
public int addMinimum(String word) {
    int n=word.length();
    if(n==1){
        return 2;
    }
    int res=0;
    int count=1;
    for(int i=0;i<n-1;i++){
        if(word.charAt(i+1)<=word.charAt(i)){
            res+=3-count;
            count=1;
        }else{
            count++;
        }
    }
    return res+(3-count);
  
}

有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~

相关推荐
身如柳絮随风扬4 小时前
Java中的CAS机制详解
java·开发语言
-dzk-6 小时前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
风筝在晴天搁浅6 小时前
hot100 78.子集
java·算法
Jasmine_llq6 小时前
《P4587 [FJOI2016] 神秘数》
算法·倍增思想·稀疏表(st 表)·前缀和数组(解决静态区间和查询·st表核心实现高效预处理和查询·预处理优化(提前计算所需信息·快速io提升大规模数据读写效率
超级大只老咪6 小时前
快速进制转换
笔记·算法
m0_706653236 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你917 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
qq_423233907 小时前
C++与Python混合编程实战
开发语言·c++·算法
TracyCoder1237 小时前
LeetCode Hot100(19/100)——206. 反转链表
算法·leetcode
m0_715575347 小时前
分布式任务调度系统
开发语言·c++·算法