news 2026/4/16 19:46:34

算法题 将字符串翻转到单调递增

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题 将字符串翻转到单调递增

926. 将字符串翻转到单调递增

问题描述

如果一个二进制字符串的每个字符都满足:'0''1'之前(即形如"000...111..."),则称该字符串为单调递增的。

给定一个二进制字符串s,你可以将其中的任意'0'翻转为'1',或将'1'翻转为'0'

返回使s单调递增所需的最少翻转次数

示例

输入: s = "00110" 输出: 1 解释: 翻转最后一位得到 "00111"。 输入: s = "010110" 输出: 2 解释: 翻转第二位和第五位得到 "000111"。 输入: s = "00011000" 输出: 2 解释: 翻转第五位和第六位得到 "00000000"。

算法思路

  1. 前缀和:对于每个可能的分割位置i0 <= i <= n):

    • 左边[0, i-1]应该全是'0',需要翻转的'1'数量 = 左边'1'的数量
    • 右边[i, n-1]应该全是'1',需要翻转的'0'数量 = 右边'0'的数量
    • 总翻转次数 = 左边'1'的数量 + 右边'0'的数量
  2. 动态规划:维护两个状态:

    • dp0:以当前位置结尾,且当前字符为'0'时的最少翻转次数
    • dp1:以当前位置结尾,且当前字符为'1'时的最少翻转次数
    • 状态转移:
      • 如果当前字符是'0'dp0不变,dp1 = min(dp0, dp1) + 1
      • 如果当前字符是'1'dp0++dp1 = min(dp0, dp1)

代码实现

方法一:前缀和

classSolution{/** * 使用前缀和计算最少翻转次数 * * @param s 二进制字符串 * @return 使字符串单调递增的最少翻转次数 */publicintminFlipsMonoIncr(Strings){intn=s.length();// 计算前缀和:prefixOnes[i] 表示 s[0...i-1] 中 '1' 的数量int[]prefixOnes=newint[n+1];for(inti=0;i<n;i++){prefixOnes[i+1]=prefixOnes[i]+(s.charAt(i)=='1'?1:0);}intminFlips=Integer.MAX_VALUE;// 枚举所有可能的分割点 i(0 <= i <= n)// 分割点 i 表示 [0, i-1] 为 '0',[i, n-1] 为 '1'for(inti=0;i<=n;i++){// 左边 [0, i-1] 中 '1' 的数量(需要翻转为 '0')intonesToLeft=prefixOnes[i];// 右边 [i, n-1] 中 '0' 的数量(需要翻转为 '1')intzerosToRight=(n-i)-(prefixOnes[n]-prefixOnes[i]);minFlips=Math.min(minFlips,onesToLeft+zerosToRight);}returnminFlips;}}

方法二:动态规划

classSolution{/** * 动态规划 * * @param s 二进制字符串 * @return 使字符串单调递增的最少翻转次数 */publicintminFlipsMonoIncr(Strings){// dp0: 当前位置为 '0' 时的最少翻转次数// dp1: 当前位置为 '1' 时的最少翻转次数intdp0=0,dp1=0;for(charc:s.toCharArray()){if(c=='0'){// 当前字符是 '0'// dp0 不变(保持为 '0',不需要翻转)// dp1 = min(dp0, dp1) + 1(翻转为 '1')dp1=Math.min(dp0,dp1)+1;}else{// 当前字符是 '1'// dp0++(翻转为 '0')// dp1 = min(dp0, dp1)(保持为 '1',不需要翻转)dp0++;dp1=Math.min(dp0,dp1);}}returnMath.min(dp0,dp1);}}

算法分析

方法时间复杂度空间复杂度
前缀和O(n)O(n)
动态规划O(n)O(1)

算法过程

输入:s = "010110"

方法一

  1. prefixOnes = [0,0,1,1,2,3,3]
  2. 枚举分割点:
    • i=0: 左边’1’数=0,右边’0’数=3 → 翻转=3
    • i=1: 左边’1’数=0,右边’0’数=2 → 翻转=2
    • i=2: 左边’1’数=1,右边’0’数=2 → 翻转=3
    • i=3: 左边’1’数=1,右边’0’数=1 → 翻转=2
    • i=4: 左边’1’数=2,右边’0’数=1 → 翻转=3
    • i=5: 左边’1’数=3,右边’0’数=1 → 翻转=4
    • i=6: 左边’1’数=3,右边’0’数=0 → 翻转=3
  3. 最小值 = 2

方法二

  1. c='0':dp0=0(保持0),dp1=1(翻转为1)→(0,1)
  2. c='1':dp0=1(翻转为0),dp1=min(0,1)=0(保持1)→(1,0)
  3. c='0':dp0=1(保持0),dp1=min(1,0)+1=1(翻转为1)→(1,1)
  4. c='1':dp0=2(翻转为0),dp1=min(1,1)=1(保持1)→(2,1)
  5. c='1':dp0=3(翻转为0),dp1=min(2,1)=1(保持1)→(3,1)
  6. c='0':dp0=3(保持0),dp1=min(3,1)+1=2(翻转为1)→(3,2)
  7. 结果:min(3,2) = 2

测试用例

publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 测试用例1:标准示例System.out.println("Test 1: "+solution.minFlipsMonoIncr("00110"));// 1// 测试用例2:另一个标准示例System.out.println("Test 2: "+solution.minFlipsMonoIncr("010110"));// 2// 测试用例3:复杂情况System.out.println("Test 3: "+solution.minFlipsMonoIncr("00011000"));// 2// 测试用例4:全0System.out.println("Test 4: "+solution.minFlipsMonoIncr("0000"));// 0// 测试用例5:全1System.out.println("Test 5: "+solution.minFlipsMonoIncr("1111"));// 0// 测试用例6:交替System.out.println("Test 6: "+solution.minFlipsMonoIncr("010101"));// 3// 测试用例7:单字符System.out.println("Test 7: "+solution.minFlipsMonoIncr("0"));// 0System.out.println("Test 8: "+solution.minFlipsMonoIncr("1"));// 0// 测试用例8:需要全翻转为0System.out.println("Test 9: "+solution.minFlipsMonoIncr("1111100000"));// 5// 测试用例9:需要全翻转为1System.out.println("Test 10: "+solution.minFlipsMonoIncr("0000011111"));// 0// 测试用例10:长字符串StringlongStr="00000000000000000000000000000000000000000000000000";System.out.println("Test 11: "+solution.minFlipsMonoIncr(longStr));// 0}

关键点

  1. 分割点

    • 单调递增字符串必然存在一个分割点
    • 枚举所有可能的分割点是最直观的思路
  2. 动态规划状态

    • dp0dp1分别表示以'0''1'结尾的最少翻转次数
    • 状态转移要考虑当前字符和之前的最优解
  3. 边界情况处理

    • '0'或全'1'的情况
    • 单字符字符串
    • 空字符串

常见问题

  1. 为什么动态规划中dp1 = min(dp0, dp1)
    • 单调递增允许'1'后面继续是'1'
    • 前面可以是以'0''1'结尾,取较小值
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 15:43:58

快速理解有源蜂鸣器驱动电平与逻辑关系图解说明

有源蜂鸣器怎么接&#xff1f;高电平开还是低电平开&#xff1f;一文讲透驱动逻辑与电路设计你有没有遇到过这样的情况&#xff1a;代码明明写了“启动蜂鸣器”&#xff0c;结果喇叭一声不响&#xff1b;或者系统一上电&#xff0c;蜂鸣器就“哇”地叫起来&#xff0c;吓人一跳…

作者头像 李华
网站建设 2026/4/16 18:13:31

用IQuest-Coder-V1快速开发:智能编程助手实战应用

用IQuest-Coder-V1快速开发&#xff1a;智能编程助手实战应用 随着大模型在代码生成领域的持续演进&#xff0c;开发者对高效、精准、可落地的编程辅助工具需求日益增长。近期&#xff0c;由九坤投资旗下至知创新研究院推出的 IQuest-Coder-V1-40B-Instruct 模型&#xff0c;凭…

作者头像 李华
网站建设 2026/4/16 16:07:40

亲测好用专科生必看8款AI论文写作软件测评

亲测好用专科生必看8款AI论文写作软件测评 2026年专科生论文写作工具测评&#xff1a;从实用到高效&#xff0c;全面解析 随着AI技术的不断进步&#xff0c;越来越多的专科生开始借助智能工具提升论文写作效率。然而&#xff0c;面对市场上琳琅满目的AI论文写作软件&#xff…

作者头像 李华
网站建设 2026/4/16 14:47:52

MediaPipe模型训练技巧:提升小脸检测准确率

MediaPipe模型训练技巧&#xff1a;提升小脸检测准确率 1. 背景与挑战&#xff1a;AI人脸隐私保护中的“小脸漏检”问题 在当前数字内容爆发式增长的背景下&#xff0c;个人隐私保护已成为图像处理领域的核心议题。尤其在社交媒体、公共监控、医疗影像等场景中&#xff0c;自…

作者头像 李华
网站建设 2026/4/16 16:09:58

AI骨骼检测在教育领域的应用:体育课动作规范检测系统

AI骨骼检测在教育领域的应用&#xff1a;体育课动作规范检测系统 1. 技术背景与教育痛点 在传统体育教学中&#xff0c;教师往往需要通过肉眼观察学生的动作是否标准&#xff0c;例如广播体操、篮球投篮或田径起跑姿势。这种方式存在明显的主观性和局限性&#xff1a;教师难以…

作者头像 李华
网站建设 2026/4/16 14:08:30

AI手势识别如何实现毫秒级响应?极速推理实战解析

AI手势识别如何实现毫秒级响应&#xff1f;极速推理实战解析 1. 引言&#xff1a;AI 手势识别与追踪的现实挑战 随着人机交互技术的不断演进&#xff0c;AI手势识别正逐步从实验室走向消费级应用。无论是智能车载系统、AR/VR设备&#xff0c;还是智能家居控制&#xff0c;用户…

作者头像 李华