news 2026/3/3 2:24:43

算法题 增减字符串匹配

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题 增减字符串匹配

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. 贪心策略?
    • 选择极值不会限制后续的选择空间
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/2 1:17:09

【风控】贝叶斯算法

一、贝叶斯定理与概率基础 1. 条件概率 贝叶斯定理建立在条件概率基础上。条件概率P(A∣B)P(A|B)P(A∣B)定义为&#xff1a; P(A∣B)P(A∩B)P(B) P(A|B) \frac{P(A \cap B)}{P(B)} P(A∣B)P(B)P(A∩B)​ 表示在事件 B 已经发生的条件下事件 A 发生的概率。这为贝叶斯推理提供了…

作者头像 李华
网站建设 2026/2/25 16:02:01

收藏!六模块Prompt结构精讲:让大模型精准听话的系统化方案

本文深度拆解六模块提示词核心结构&#xff08;角色/任务、核心原则、上下文处理、CoT、输出规范、Few-Shot&#xff09;&#xff0c;为程序员与大模型初学者提供可直接复用的高效Prompt编写指南&#xff0c;助力快速掌握让大模型精准执行任务的关键技巧。文中同步分享借助大模…

作者头像 李华
网站建设 2026/2/16 13:30:30

AI大模型:开启智能新时代的技术引擎

引言​在当今科技飞速发展的时代&#xff0c;AI 大模型无疑是最耀眼的明星之一。从智能语音助手到图像生成&#xff0c;从智能客服到智能驾驶&#xff0c;AI 大模型正以惊人的速度渗透到我们生活的方方面面&#xff0c;深刻地改变着我们的工作、学习和生活方式。它不仅推动了科…

作者头像 李华
网站建设 2026/3/2 1:23:32

基于springboot保健品营销管理系统的设计与实现

基于springboot保健品营销管理系统的设计与实现 一、系统总体设计 基于SpringBoot的保健品营销管理系统以“规范营销流程、精准客户运营、保障合规销售”为核心目标&#xff0c;解决传统保健品营销中客户管理混乱、库存与订单不同步、合规记录缺失等问题&#xff0c;适配中小型…

作者头像 李华
网站建设 2026/3/1 7:09:01

C# 基于OpenCv的视觉工作流-章12-双边滤波

C# 基于OpenCv的视觉工作流-章12-双边滤波 本章目标&#xff1a; 一、双边滤波&#xff1b;一、双边滤波&#xff1b; 双边滤波以卷积计算&#xff08;章6腐蚀有介绍&#xff09;为基础&#xff0c;保留边缘的同时能对边缘内区域进行平滑&#xff0c;相当于做美颜。OpenCv双边滤…

作者头像 李华
网站建设 2026/2/20 1:20:29

冥想第一千七百六十五天(1765)

1.今天2026.1.25天气巨好&#xff0c;温度达到了18度&#xff0c;有种春暖花开的感觉&#xff0c;但这是短暂的&#xff0c;看天气预报&#xff0c;明天就开始降温了。项目上全力以赴的一天。 2.感谢父母&#xff0c;感谢朋友&#xff0c;感谢家人&#xff0c;感谢不断进步的自…

作者头像 李华