news 2026/5/31 3:17:07

面试必看:单调递增的数字

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
面试必看:单调递增的数字

学习笔记:LeetCode 738. 单调递增的数字

题目描述

当且仅当每个相邻位数上的数字x xxy yy满足x ≤ y x \le yxy时,我们称这个整数是单调递增数字
给定一个整数n nn,返回小于或等于n nn的最大单调递增数字

示例

  • 输入:n = 10 n=10n=10,输出:9 99
  • 输入:n = 1234 n=1234n=1234,输出:1234 12341234
  • 输入:n = 332 n=332n=332,输出:299 299299

数据范围
0 ≤ n ≤ 10 9 0 \le n \le 10^90n109


1. 算法分类

贪心类
本题是贪心算法在数位操作场景的经典应用,依托局部最优推导全局最优的核心思想实现求解。


2. 问题核心特征与算法适配性分析

核心特征

  1. 硬性约束:目标数字每一位必须满足非递减(单调递增),即s [ i ] ≤ s [ i + 1 ] s[i] \le s[i+1]s[i]s[i+1]
  2. 优化目标:在满足约束的前提下,找到小于等于原数的最大值,高位数值优先级远高于低位;
  3. 处理形式:整数适合转换为字符串进行逐位修改、遍历操作,大幅简化数位处理逻辑。

为什么适配贪心算法

  1. 策略匹配需求:贪心算法优先保证高位数字尽可能大,通过局部数位的修正,直接推导出全局最优解,完美契合本题的优化目标;
  2. 效率最优:仅需两次线性遍历数字位数,时间复杂度极低,远优于暴力枚举等方案;
  3. 操作简洁:针对违规数位执行退位修正+后置位补9,逻辑直观易实现,无复杂计算。

备选方案对比

解法时间复杂度空间复杂度弃选原因
暴力枚举O ( n ⋅ l e n ) O(n \cdot len)O(nlen)O ( 1 ) O(1)O(1)n nn最大为10 9 10^9109,会直接超时,无法通过测试
动态规划O ( l e n ⋅ 10 ) O(len \cdot 10)O(len10)O ( l e n ⋅ 10 ) O(len \cdot 10)O(len10)状态定义繁琐,实现复杂,相比贪心无效率与编码优势

3. 问题关键词

单调递增数字、非递减数位、最大取值、贪心算法、数位处理、退位补9、字符串转换


4. 解题模式识别

题型定位

本题属于数位约束类贪心问题,具备标准化解题特征:

  1. 对整数的每一位数字定义明确约束条件;
  2. 求解满足约束条件的极值数字(最大值/最小值);
  3. 通用解题模板:数字转字符串→ \to定位违规数位→ \to贪心策略修正→ \to字符串转回数字。

拓展场景

该解题模板可迁移至同类数位优化问题,如:拼接数字得到最大/最小值、带约束的数位构造问题等。


5. 问题分析

  1. 违规判定:从前向后遍历,若出现s [ i ] > s [ i + 1 ] s[i] > s[i+1]s[i]>s[i+1],则违反单调递增规则;
  2. 连锁反应:对当前位退位后,可能导致前序数位也产生违规,因此选择从后向前遍历,一次性处理所有连锁违规问题;
  3. 最优修正规则:违规位退位后,将其后续所有位置为9,能保证修正后的数字是满足条件的最大值;
  4. 边界兼容:字符串转整数函数会自动忽略前导零,无需额外处理边界用例。

6. 解题思路

基于贪心策略,分三步完成求解:

步骤1:格式转换

将整数n nn转换为字符串,方便逐位遍历与修改操作。

步骤2:逆向遍历修正违规位

初始化标记位flag(标记后续需要置9的起始下标),默认值为字符串长度。
从倒数第二位开始从后向前遍历字符串:

  • 若当前位数字s [ i ] > s[i] >s[i]>后一位数字s [ i + 1 ] s[i+1]s[i+1],将当前位退位s[i]--,并更新标记位flag = i+1

步骤3:统一补9并转换结果

从标记位flag开始,将后续所有数位置为9,最后将修正后的字符串转换为整数,即为最终答案。


7. 解题代码(C++)

#include<string>usingnamespacestd;classSolution{public:intmonotoneIncreasingDigits(intn){// 将数字转换为字符串,方便逐位操作string s=to_string(n);intlen=s.size();// 标记位:记录需要置为9的起始下标,初始为字符串长度(无违规则不执行置9)intflag=len;// 从后向前遍历,定位并修正违规数位for(inti=len-2;i>=0;i--){if(s[i]>s[i+1]){// 当前位退位s[i]--;// 更新标记位,后续所有位需要置9flag=i+1;}}// 将标记位及之后的所有数位统一置为9,保证数值最大for(inti=flag;i<len;i++){s[i]='9';}// 字符串转换为整数返回,自动忽略前导零returnstoi(s);}};

代码关键说明

  1. 字符串处理:规避了数学取位、拼接的复杂运算,代码更简洁;
  2. 标记位flag:统一记录置9起始位置,避免重复遍历,提升执行效率;
  3. 逆向遍历:解决退位引发的连锁违规问题,保证所有数位最终满足约束;
  4. stoi函数:自动处理前导零,适配n = 0 n=0n=0等边界场景。

8. 复杂度分析

时间复杂度

O ( l e n ) O(len)O(len)l e n lenlen为数字n nn的位数(最多10位)。
算法包含两次线性遍历,整体为常数级别的线性时间复杂度,执行效率极高。

空间复杂度

O ( l e n ) O(len)O(len),用于存储数字对应的字符串,属于必要的辅助空间。


关键注意事项

  1. 遍历方向:必须采用从后向前遍历,才能处理退位带来的前序数位连锁违规问题;
  2. 独立置9:统一将标记位后所有位置9,是保证结果为最大值的核心操作;
  3. 结果转换:利用库函数自动处理前导零,简化边界场景的代码逻辑。

总结

  1. 本题最优解法为贪心算法,通过退位修正+后置位统一补9的策略,高效求解目标值;
  2. 核心技巧是将整数转为字符串处理数位,搭配逆向遍历解决连锁违规问题;
  3. 该方案是数位约束类贪心题目的通用模板,可直接迁移至同类场景。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 13:50:48

工业边缘计算:不止是降本增效,更是重塑制造DNA

当我们谈论“未来工厂”时&#xff0c;脑海中浮现的往往是科幻电影里全自动、无人工的冰冷画面。但真正的未来&#xff0c;远不止于此。2030年的工厂&#xff0c;将不再是简单机器的堆砌&#xff0c;而是一个具备感知、思考、决策和协同能力的“智慧生命体”。驱动这一变革的核…

作者头像 李华
网站建设 2026/5/29 1:41:31

从云端到边缘:YOLOv8模型轻量化与RK3588J部署避坑指南

在智能制造、智慧安防、无人巡检等工业场景中&#xff0c;实时、精准的视觉AI分析能力正变得至关重要。然而&#xff0c;将强大的AI算法&#xff0c;例如当前流行的目标检测模型YOLOv8&#xff0c;直接部署到工厂车间、仓库或户外现场的边缘设备上&#xff0c;却面临巨大挑战&a…

作者头像 李华
网站建设 2026/5/28 18:18:40

时代的拷问——我们为何而数字化?

引言 我们正被一场名为“数字化”的洪流裹挟前行。从国家顶层战略到街头巷尾的商铺&#xff0c;从跨国集团的董事会到初创公司的咖啡桌&#xff0c;“数字化转型”已成为这个时代最高频、最迫切&#xff0c;也最令人焦虑的词汇。企业如同参加一场军备竞赛&#xff0c;不断购入云…

作者头像 李华
网站建设 2026/5/28 13:50:50

JSP中h3标签是什么?怎么用?

在JSP开发中&#xff0c;h3标签是HTML标题元素的一种&#xff0c;用于定义网页内容的第三级标题。很多初学者看到这个标签时会产生疑问&#xff1a;它到底是JSP特有的标签还是普通的HTML标签&#xff1f;实际上&#xff0c;h3是标准的HTML标签&#xff0c;在JSP中可以直接使用&…

作者头像 李华