当前位置: 首页 > news >正文

算法题 增减字符串匹配

942. 增减字符串匹配

问题描述

给定只含"I"(增加)和"D"(减少)的字符串s,令n = s.length

根据s构造一个排列perm(长度为n + 1),使得对于所有的i

  • 如果s[i] == 'I',则perm[i] < perm[i + 1]
  • 如果s[i] == 'D',则perm[i] > perm[i + 1]

返回满足条件的任意一个排列perm

示例

输入: s = "IDID" 输出: [0,4,1,3,2] 解释: - I: 0 < 4 - D: 4 > 1 - I: 1 < 3 - D: 3 > 2 输入: s = "III" 输出: [0,1,2,3] 输入: s = "DDI" 输出: [3,2,0,1] 解释: - D: 3 > 2 - D: 2 > 0 - I: 0 < 1

算法思路

贪心

核心思想

  • 使用两个指针:low = 0high = n
  • 遍历字符串s
    • 如果遇到'I',选择当前最小可用数字low,然后low++
    • 如果遇到'D',选择当前最大可用数字high,然后high--
  • 最后将剩余的数字(此时low == high)添加到结果末尾

代码实现

方法一:双指针贪心

classSolution{/** * 根据增减字符串构造排列 * * @param s 只包含 'I' 和 'D' 的字符串 * @return 满足条件的排列数组 */publicint[]diStringMatch(Strings){intn=s.length();int[]result=newint[n+1];intlow=0;// 当前最小可用数字inthigh=n;// 当前最大可用数字// 遍历字符串s,构造前n个元素for(inti=0;i<n;i++){if(s.charAt(i)=='I'){// 遇到'I',选择最小的可用数字result[i]=low++;}else{// s.charAt(i) == 'D'// 遇到'D',选择最大的可用数字result[i]=high--;}}// 最后一个位置,此时low == highresult[n]=low;// 或者 result[n] = high;returnresult;}}

算法分析

  • 时间复杂度:O(n)
    • 只需要遍历字符串一次
  • 空间复杂度:O(1)
    • 只使用了常数个额外变量

算法过程

输入:s = "IDID"

  1. 初始化:low = 0,high = 4,result = [?, ?, ?, ?, ?]
  2. i=0,s[0]='I'result[0] = 0,low = 1
  3. i=1,s[1]='D'result[1] = 4,high = 3
  4. i=2,s[2]='I'result[2] = 1,low = 2
  5. i=3,s[3]='D'result[3] = 3,high = 2
  6. 最后:result[4] = 2
  7. 结果:[0,4,1,3,2]

输入:s = "DDI"

  1. 初始化:low = 0,high = 3,result = [?, ?, ?, ?]
  2. i=0,'D'result[0] = 3,high = 2
  3. i=1,'D'result[1] = 2,high = 1
  4. i=2,'I'result[2] = 0,low = 1
  5. 最后:result[3] = 1
  6. 结果:[3,2,0,1]

输入:s = "III"

  1. result[0] = 0,low = 1
  2. result[1] = 1,low = 2
  3. result[2] = 2,low = 3
  4. result[3] = 3
  5. 结果:[0,1,2,3]

测试用例

publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 测试用例1:标准示例Strings1="IDID";int[]result1=solution.diStringMatch(s1);System.out.println("Test 1: "+Arrays.toString(result1));// [0,4,1,3,2]// 验证结果verifyResult(s1,result1);// 应该输出 Valid// 测试用例2:全增加Strings2="III";int[]result2=solution.diStringMatch(s2);System.out.println("Test 2: "+Arrays.toString(result2));// [0,1,2,3]verifyResult(s2,result2);// Valid// 测试用例3:全减少Strings3="DDD";int[]result3=solution.diStringMatch(s3);System.out.println("Test 3: "+Arrays.toString(result3));// [3,2,1,0]verifyResult(s3,result3);// Valid// 测试用例4:混合情况Strings4="DDI";int[]result4=solution.diStringMatch(s4);System.out.println("Test 4: "+Arrays.toString(result4));// [3,2,0,1]verifyResult(s4,result4);// Valid// 测试用例5:单字符Strings5="I";int[]result5=solution.diStringMatch(s5);System.out.println("Test 5: "+Arrays.toString(result5));// [0,1]verifyResult(s5,result5);// ValidStrings6="D";int[]result6=solution.diStringMatch(s6);System.out.println("Test 6: "+Arrays.toString(result6));// [1,0]verifyResult(s6,result6);// Valid// 测试用例6:长字符串Strings7="IDIDIDIDID";int[]result7=solution.diStringMatch(s7);System.out.println("Test 7: Length = "+result7.length);// 11verifyResult(s7,result7);// Valid// 测试用例7:交替模式Strings8="IDIDID";int[]result8=solution.diStringMatch(s8);verifyResult(s8,result8);// ValidSystem.out.println("Test 8: Valid = "+isValidPermutation(result8,6));}privatestaticvoidverifyResult(Strings,int[]perm){booleanvalid=true;for(inti=0;i<s.length();i++){if(s.charAt(i)=='I'&&perm[i]>=perm[i+1]){valid=false;break;}if(s.charAt(i)=='D'&&perm[i]<=perm[i+1]){valid=false;break;}}// 检查是否是0到n的排列boolean[]used=newboolean[perm.length];for(intnum:perm){if(num<0||num>=perm.length||used[num]){valid=false;break;}used[num]=true;}System.out.println("验证: "+(valid?"Valid":"Invalid"));}privatestaticbooleanisValidPermutation(int[]perm,intn){boolean[]used=newboolean[n+1];for(intnum:perm){if(num<0||num>n||used[num]){returnfalse;}used[num]=true;}returntrue;}

关键点

  1. 贪心策略

    • 选择极值(最小或最大)为后续操作保留最大灵活性
  2. 数字范围

    • 必须使用0n的所有整数恰好一次
    • 双指针保证了这一点
  3. 边界处理

    • 字符串长度为n,结果数组长度为n+1
    • 最后一个元素自动确定(low == high

常见问题

  1. 贪心策略?
    • 选择极值不会限制后续的选择空间
http://www.jsqmd.com/news/249287/

相关文章:

  • 揭秘Redis内存回收黑科技:面试必看!
  • 基于Django的蔬菜批发管理系统设计与实现
  • 【风控】逻辑回归算法
  • 导师推荐!8款AI论文软件测评:研究生开题报告必备工具
  • 【收藏】大模型从入门到实战:程序员必学的AI技能,抓住技术红利就现在
  • 基于Django的天虹商场管理系统设计与实现
  • 基于Django的鲜花预订购买管理系统设计与实现
  • 收藏!程序员转型难如蜀道?4大核心症结拆解+突破方向(附大模型时代适配指南)
  • 收藏!六模块Prompt结构精讲:让大模型精准听话的系统化方案
  • Formizee:把表单数据牢牢握在手里的开源神器
  • ‌当AI能自己写测试、执行、分析、报告,人类该做什么?
  • PVE添加ssd硬盘默认新建pool,处理
  • 基于springboot的毕业生招聘职位推荐系统
  • 【计算机毕业设计案例】基于SpringBoot的药店商品管理、库存管理、销售管理、采购管理管理系统设计与实现基于SpringBoot的药店管理系统设计与实现(程序+文档+讲解+定制)
  • 告别查重 + AIGC 双重警报!宏智树 AI 教你给论文注入人工原创灵魂
  • ‌35岁测试人转型指南:AI时代,你的核心竞争力是什么?
  • 京东价格API:历史价格趋势分析与定价参考技术实现
  • 知从木牛MCAL配置功能介绍
  • 市场份额超三成,志凌海纳 SmartX 连续 11 个季度领跑超融合软件中国市场
  • Java毕设项目推荐-基于Springboot实现药店管理系统基于SpringBoot的药店管理系统设计与实现【附源码+文档,调试定制服务】
  • 软件测试面试题小结(一)
  • ‌2026年,测试工程师会消失吗?
  • pve在迁移机器后更换vmbr物理网卡配置后导致默认虚拟网卡绑定到原始物理网卡下
  • Vercel 重磅发布 agent-browser:AI Agent 浏览器自动化的新纪元来了
  • 人工智能下游应用端产业链梳理与投资逻辑分析【20260115】
  • python+Java的网盘程序升级版。无感知备份文档,保护数据资产利器。
  • 人工智能-AI下游应用端核心赛道(教育/医疗/金融)个股对比表【20260115】
  • 红外图像水管管道破裂漏水检测数据集VOC+YOLO格式93张1类别
  • sward快速上手教程,从安装到入门
  • 无人机航拍黑匣子目标检测数据集_91张高清图像_907个精确标注_适用于计算机视觉模型训练与评估