
方法一:暴力(超时)
java
class Solution {
//判断一个数字的各位上是否是递增
boolean checkNum(int num){
int max = 10;
while(num != 0){
int t = num % 10;
if(max >= t){
max = t;
}else{
return false;
}
num = num/10;
}
return true;
}
public int monotoneIncreasingDigits(int n) {
for(int i = n;i > 0;i --){ //从大到小遍历
if(checkNum(i)){
return i;
}
}
return 0;
}
}
方法二:贪心。
思路:
1.求小于等于n的最大单调递增的整数,以一个两位数字为例。如:98,一旦出现strNum[i - 1] > strNum[ i ]的情况(非单调递增),首先想让strNum[i - 1]--,然后strNum[i]给为9,这样这个整数就是89,即89是小于98的最大的单调递增的整数。
2.遍历顺序:举个例子,332,如果从前向后遍历,则为329,此时2又小于第一位的3了,真正的结果应该是229。因此应该从后向前遍历,这样可以重复利用上次比较得出的结果。从后向前遍历332的数值变化为:332 -> 329 -> 229。
3.确立了遍历顺序后,此时局部最优可以推出全局最优,找不出反例,试试贪心。
函数解释:String.join(分隔符,字符串数组或集合)。
第一个参数"":分隔符,这里使用空字符串,表示元素之间不加任何分隔符。
第二个参数strings:表示要连接的字符串数组。
附代码:
java
class Solution {
public int monotoneIncreasingDigits(int n) {
//将整数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));
}
}
上述方法中创建了String数组,多次使用了Integer.parseInt方法,这导致不管是耗时还是空间占用都非常高,用时12ms。可以在char数组上原地修改,耗时1ms。
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));
}
}