news 2026/4/18 11:26:10

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

作者头像

张小明

前端开发工程师

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/17 22:50:16

绿色安全框提示功能解析:AI人脸卫士WebUI使用指南

绿色安全框提示功能解析&#xff1a;AI人脸卫士WebUI使用指南 1. 技术背景与核心价值 在数字化时代&#xff0c;图像和视频的传播变得前所未有的便捷。然而&#xff0c;随之而来的人脸隐私泄露风险也日益加剧——无论是社交媒体上的合照分享&#xff0c;还是监控影像的公开发…

作者头像 李华
网站建设 2026/4/17 16:29:42

小白也能玩转大模型:手把手教你用HY-MT1.5-1.8B搭建离线翻译服务

小白也能玩转大模型&#xff1a;手把手教你用HY-MT1.5-1.8B搭建离线翻译服务 1. 引言 在全球化日益深入的今天&#xff0c;跨语言沟通已成为企业、科研乃至个人日常的重要需求。然而&#xff0c;在许多实际场景中——如野外作业、军事通信、航空航海或对数据隐私要求极高的行…

作者头像 李华
网站建设 2026/4/17 22:48:40

GLM-4.6V-Flash-WEB企业部署:高可用架构设计实战案例

GLM-4.6V-Flash-WEB企业部署&#xff1a;高可用架构设计实战案例 智谱最新开源&#xff0c;视觉大模型。 快速开始 部署镜像&#xff08;单卡即可推理&#xff09;&#xff1b;进入Jupyter&#xff0c;在 /root 目录&#xff0c;运行 1键推理.sh&#xff1b;返回实例控制台&am…

作者头像 李华
网站建设 2026/4/17 22:43:07

UE5 C++(23-4):

&#xff08;134&#xff09; &#xff08;135&#xff09; 谢谢

作者头像 李华
网站建设 2026/4/18 0:25:29

AI人脸隐私卫士性能测试:毫秒级打码实战测评

AI人脸隐私卫士性能测试&#xff1a;毫秒级打码实战测评 1. 背景与需求分析 随着社交媒体和数字影像的普及&#xff0c;个人隐私保护问题日益突出。在发布合照、会议记录或街拍照片时&#xff0c;未经处理的人脸信息极易造成隐私泄露。传统手动打码方式效率低下&#xff0c;难…

作者头像 李华
网站建设 2026/4/18 0:26:49

AI人脸隐私卫士能否部署在树莓派?低算力设备实测

AI人脸隐私卫士能否部署在树莓派&#xff1f;低算力设备实测 1. 背景与挑战&#xff1a;AI隐私保护的边缘落地难题 随着智能摄像头、家庭监控和社交分享的普及&#xff0c;图像中的人脸隐私泄露风险日益加剧。尽管云端AI服务能高效完成人脸打码&#xff0c;但数据上传本身即构…

作者头像 李华