刷题顺序按照代码随想录建议
题目描述
英文版描述
An integer has monotone increasing digits if and only if each pair of adjacent digits x and y satisfy x <= y.
Given an integer n, return the largest number that is less than or equal to n with monotone increasing digits.
Example 1:
Input: n = 10 Output: 9
Example 2:
Input: n = 1234 Output: 1234
Example 3:
Input: n = 332 Output: 299
Constraints:
- 0 <= n <= 10^9
英文版地址
中文版描述
当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。
给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。
示例 1:
输入: n = 10 输出: 9
示例 2:
输入: n = 1234 输出: 1234
示例 3:
输入: n = 332 输出: 299
提示:
- 0 <= n <= 10^9
中文版地址
解题方法
暴力法
第一反应,就减1减1一直判断呗~(果然超时了(˶‾᷄ ⁻̫ ‾᷅˵),不过方法肯定是对的嘿嘿( ̄∇ ̄))

java
class Solution {
public int monotoneIncreasingDigits(int n) {
if (n <= 10) {
return n - 1;
}
int result = n;
while (result > 0) {
if (isValid(result)) {
return result;
}
result = result - 1;
}
return result;
}
private boolean isValid(int result) {
String r = result + "";
int cur = 0;
for (int i = 0; i < r.length(); i++) {
char c = r.charAt(i);
int i1 = Integer.parseInt(c + "");
if (cur > i1) {
return false;
}
cur = i1;
}
return true;
}
}
复杂度分析
- 时间复杂度:O(m),m表示数字 n 的位数,但是这个结果不确定(欢迎批评指正~~),因为没算isValid()方法中的for循环,这个for循环的时间复杂度取决于整数的位数
- 空间复杂度:O(1)
贪心法
暴力解法优化后

java
class Solution {
public int monotoneIncreasingDigits(int n) {
int result = n;
if (result < 10) {
return result;
}
if (result < 100) {
int unit = result % 10;
int decade = result / 10;
if (decade > unit) {
return (decade - 1) * 10 + 9;
} else {
return result;
}
}
String ns = n + "";
char[] charsN = ns.toCharArray();
int index = charsN.length;
// 332
for (int i = charsN.length - 1; i > 0; i--) {
int ci = Integer.parseInt(charsN[i] + "");
int prei = Integer.parseInt(charsN[i - 1] + "");
if (prei > ci) {
charsN[i - 1]--;
index = i;
}
}
for (int i = 0; i < charsN.length; i++) {
if (i >= index) {
charsN[i] = '9';
}
}
result = Integer.parseInt(String.valueOf(charsN));
return result;
}
}
复杂度分析
- 时间复杂度:O(m),m表示数字 n 的位数
- 空间复杂度:O(m),额外的chars[]占用空间
字符串版

java
class Solution {
public int monotoneIncreasingDigits(int N) {
String[] strings = (N + "").split("");
int start = strings.length;
for (int i = strings.length - 1; i > 0; i--) {
if (Integer.parseInt(strings[i]) < Integer.parseInt(strings[i - 1])) {
strings[i - 1] = (Integer.parseInt(strings[i - 1]) - 1) + "";
start = i;
}
}
for (int i = start; i < strings.length; i++) {
strings[i] = "9";
}
return Integer.parseInt(String.join("",strings));
}
}
这里用到了Integer.parseInt(String.join("",strings))来合并字符串数组并转化为数字,不过整个代码多次使用Integer.parseInt()方法,这导致不管是耗时还是空间占用都非常高,后面有数组优化版
复杂度分析
- 时间复杂度:O(m),m表示数字 n 的位数
- 空间复杂度:O(m),额外的string[]占用空间
数组优化版

java
class Solution {
public int monotoneIncreasingDigits(int n) {
String s = String.valueOf(n);
char[] chars = s.toCharArray();
int start = s.length();
for (int i = s.length() - 2; i >= 0; i--) {
if (chars[i] > chars[i + 1]) {
chars[i]--;
start = i+1;
}
}
for (int i = start; i < s.length(); i++) {
chars[i] = '9';
}
return Integer.parseInt(String.valueOf(chars));
}
}
可以看到优化效果很明显,这个其实跟我的第一版思路和方式都一样,不过相比我的那版对于1位和2位的整数做单独处理,这个代码兼容了各个位数的整数,此外有几点很实用的操作:
- chars[i]--:如果chars[]可以直接使用--来操作
- Integer.parseInt(String.valueOf(chars)):跟上面的Integer.parseInt(String.join("",strings))类似,这段代码可以把chars[]里所有的数字连起来,然后转换成一个数字
复杂度分析
- 时间复杂度:O(m),m表示数字 n 的位数
- 空间复杂度:O(m),额外的chars[]占用空间