🚩传送门:https://leetcode-cn.com/problems/monotone-increasing-digits/

题目

给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。

(当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。)

示例 1:

输入: N = 10 输出: 9

示例 2:

输入: N = 1234 输出: 1234

示例 3:

输入: N = 332 输出: 299

说明: N 是在 [ 0, 109 ] 范围内的一个整数。

题意解释:整个数字要符合依次递增

图示思路:

  1. 1 1开始 2 不符合**前小后大 **】 3 **i后退,str[i-1]减1 **】<br />![1608041237(1).png](https://cdn.nlark.com/yuque/0/2020/png/2955945/1608041265049-03418875-b900-4f82-809e-c093cd001246.png#height=195&id=GFrp2&margin=%5Bobject%20Object%5D&name=1608041237%281%29.png&originHeight=296&originWidth=351&originalType=binary&ratio=1&size=9399&status=done&style=none&width=231) ![1608041313(1).png](https://cdn.nlark.com/yuque/0/2020/png/2955945/1608041321145-9e6f5535-1fa4-47c5-9c24-a17b90da1c72.png#height=205&id=wWiGP&margin=%5Bobject%20Object%5D&name=1608041313%281%29.png&originHeight=447&originWidth=440&originalType=binary&ratio=1&size=18554&status=done&style=none&width=202) ![1608041393(1).png](https://cdn.nlark.com/yuque/0/2020/png/2955945/1608041449784-b4096e81-b4ba-4f44-9f0e-129fdbd47d4a.png#height=203&id=LPU94&margin=%5Bobject%20Object%5D&name=1608041393%281%29.png&originHeight=436&originWidth=576&originalType=binary&ratio=1&size=21371&status=done&style=none&width=268)

图4 【重复图3的过程】 图5【极限情况,i一路后退至0
1608042029(1).png 1608042060(1).png

解题思路:贪心

官方文档:给定是贪婪,暂时不清楚贪在哪里。

  1. 将 int 类型转换为 String 类型 (目的便于当作数组计算)
  2. 首先从下标 1开始,一直遍历到 N ( 数字个数 )直至不符合【前小后大】为止。即如 图1 图2 所示
    • if ( str [ i ] >= str [ i-1 ] ) i++ 【即后面的数字大于前面的数字,则继续向后遍历】即 图1 向 图2的过程
    • else { str[i-1]-=1 ,i-=1} 【即后面数小于前面的数字,所以前面数字先减一看是否还能满足比前面数字大】即图 3所示
  3. 如果持续不满足前大后小,则重复过程2,直至满足或者 i 为0
    • 如果 i 持续后退减1直至 i =0 ,则后面数字一律用9填
    • 如果后退的中途减 1满足了前大后小,则 i 后面的数字用9填充。

官方代码

  1. # include<iostream>
  2. # include<string>
  3. using namespace std;
  4. int monotoneIncreasingDigits(int N) {
  5. string str = to_string(N);
  6. int i = 1; //从1开始遍历直至末尾N结束
  7. while (i < str.length()&& str[i] >= str[i - 1]) {//目的:找出第一个不符合前小后大的数字
  8. //i在范围内,并且满足后大前小,则i++
  9. i++;
  10. }
  11. //出第一个while有两种可能,要么到了末尾,整个数组全满足,要么中途出现不满足
  12. if (i == str.length()) {//整个数组满足,数组输出即可
  13. ;//啥也不需要做
  14. }
  15. else {//中途不满足,出现了前大后小情形
  16. while (i>0&&str[i] < str[i - 1]) {//目的:找到最终的回退点
  17. str[i - 1] -= 1;//前数减1
  18. i--;//下标后退
  19. }
  20. i++;//是从满足前小后大的数字开始后面置9
  21. }
  22. while (i < str.length()) {
  23. str[i] = '9';
  24. i++;
  25. }
  26. return stoi(str);
  27. }
  28. int main(void) {
  29. cout << monotoneIncreasingDigits(120) << endl;
  30. system("pause");
  31. return 0;
  32. }