news 2026/2/11 0:20:47

算法题 增减字符串匹配

作者头像

张小明

前端开发工程师

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/2/9 7:57:56

【风控】逻辑回归算法

一、逻辑回归算法原理与公式 逻辑回归是风控领域最核心的信用评分与违约预测算法之一&#xff0c;它本质上是一种广义线性模型&#xff0c;用于预测二分类问题&#xff08;如用户违约与否&#xff09;。相比普通线性回归&#xff0c;逻辑回归能够保证预测结果落在[0,1][0,1][0,…

作者头像 李华
网站建设 2026/2/7 8:50:48

基于springboot的毕业生招聘职位推荐系统

基于springboot的毕业生招聘职位推荐系统的设计与实现 一、系统总体设计 基于SpringBoot的毕业生招聘职位推荐系统以“精准匹配岗位需求、提升求职效率、优化招聘体验”为核心目标&#xff0c;解决传统招聘中毕业生与岗位信息不对称、匹配效率低、筛选成本高的问题&#xff0c;…

作者头像 李华
网站建设 2026/2/10 12:47:59

Formizee:把表单数据牢牢握在手里的开源神器

Formizee&#xff1a;把表单数据牢牢握在手里的开源神器 哈罗大家好&#xff01;今天给大家安利一个在 GitHub 上挖到的宝藏开源项目——Formizee。是不是经常有这样的困扰&#xff1a;想在网站或应用里加个表单功能&#xff0c;自己写后端逻辑又太麻烦&#xff0c;用商业平台…

作者头像 李华
网站建设 2026/2/10 5:31:57

无人机航拍黑匣子目标检测数据集_91张高清图像_907个精确标注_适用于计算机视觉模型训练与评估

无人机航拍黑匣子目标检测数据集分析报告 引言与背景 随着计算机视觉技术的快速发展&#xff0c;目标检测在各个领域的应用日益广泛&#xff0c;特别是在航拍图像分析方面具有重要价值。无人机航拍视角独特&#xff0c;能够从高空俯瞰地面场景&#xff0c;为目标监测、资源调…

作者头像 李华
网站建设 2026/2/10 7:20:00

人工智能下游应用端产业链梳理与投资逻辑分析【20260115】

文章目录 人工智能下游应用端产业链梳理与投资逻辑分析 一、 自研大模型企业:掌握核心技术,构筑竞争壁垒 二、 绑定头部大厂的相关个股:借势生态,快速落地 2.1 绑定智谱AI:核心大模型生态伙伴 2.2 绑定字节跳动:流量与技术双轮驱动 2.3 绑定阿里:电商与企业服务生态核心…

作者头像 李华
网站建设 2026/2/8 2:57:40

Qt 小技巧:如何用 Q_PROPERTY 管理属性

在 Qt 开发中&#xff0c;属性是对象的重要组成部分。尤其是在与 UI 交互时&#xff0c;如何高效、清晰地管理属性就显得尤为重要。今天&#xff0c;我们将深入探讨 Qt 中的 Q_PROPERTY 宏&#xff0c;它是如何帮助我们简化属性的声明、管理与使用的。如果你曾经在 Qt 中编写过…

作者头像 李华