1. question: 单调递增的数字(中等) 当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。
给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。
来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/monotone-increasing-digits 
示例 1:
 
示例 2:
 
示例 3:
 
提示:
 
2. answers 这道题本质上是求(0, n]之间最大的单调递增数。最开始想的是回溯法。利用当前位置上数字的取值区间,每次尽可能地选择最大值,来回溯选择。 采用回溯法,需要注意的是,当前位置的取值区间,因为存在(当前位前面所有高位)借位的情况。
代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 public  class  Solution_0108   {    public  boolean  tag = false ;     public  void  recur (char [] chars, int  index, int [] result, boolean  isBorrow)   {         if (index == chars.length) {             tag = true ;             return ;         }                  int  pre;                  int  range;         if (index == 0 ) {                          pre = -1 ;             range = chars[index] - '0' ;         }         else  {             pre = result[index - 1 ];                                                    if (!isBorrow) range = chars[index] - '0' ;             else  range = 9 ;         }         for  (int  i = range; i >= 0 ; i--) {                          if (i >= pre) {                 result[index] = i;                                                   recur(chars, index + 1 , result, isBorrow || i != range);                                  if (tag) return ;                              }         }     }     public  int  monotoneIncreasingDigits (int  n)   {         String number = n + "" ;         char [] chars = number.toCharArray();         int [] result = new  int [chars.length];         recur(chars, 0 , result, false );         int  res = 0 ;         for  (int  i = 0 ; i < result.length; i++) {             res += result[i] * Math.pow(10 , result.length - 1  - i);         }         return  res;     }     public  static  void  main (String[] args)   {         Solution_0108 s = new  Solution_0108();         int  i = s.monotoneIncreasingDigits(999998 );         System.out.println(i);     } } 
 
参考了题解,实际上没必要回溯。采用贪心法,只要找到不满足要求的最高位即可,将其减一,后续所有的值均为9。 
但是怎么找呢?从左到右,如果从左到右,因为需要减一,就可能导致已经遍历的高位不满足要求(即低位影响高位 )。比如99998,此时在最后98不满足要求,修改为89,显然99989也不满足要求。
因此需要从右到左遍历,因为本来就是从低位向高位遍历,即使修改了低位,导致高位不满足要求,但是在后续遍历的时候,就会修改高位的。代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public  class  Solution_0108_02   {    public  int  monotoneIncreasingDigits (int  n)   {         String s = n + "" ;         char [] chars = s.toCharArray();         int  start = chars.length;                  for  (int  i = chars.length - 1 ; i > 0 ; i--) {                          if (chars[i] - '0'  < chars[i - 1 ] - '0' ) {                 chars[i - 1 ] = (char ) (chars[i - 1 ] - 1 );                 start = i;             }         }                  for  (int  i = start; i < chars.length; i++) {             chars[i] = '9' ;         }         int  res = 0 ;         for  (int  i = 0 ; i < chars.length; i++) {             res += (chars[i] - '0' ) * Math.pow(10 , chars.length - 1  - i);         }         return  res;     }     public  static  void  main (String[] args)   {         Solution_0108_02 s = new  Solution_0108_02();         int  i = s.monotoneIncreasingDigits(332 );         System.out.println(i);     } } 
 
3. 备注 参考力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 (leetcode-cn.com) ,代码随想录 (programmercarl.com) 。