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) 。