力扣738. 单调递增的数字

题目来源(力扣):

https://leetcode.cn/problems/monotone-increasing-digits/description/

题目描述:

给一个数n,要求返回一个最大的数num,使得num<=n,且num从左到右是(非严格)单调递增的。
例如,n=324,
则num为299

基本思路:

可以用搜索实现,但是不是此题的最优解。
通过一些简单的样例分析可以发现,答案往往呈现出x999的模样。
从某位开始就是连续的9,我们只需要找到这个位置wei即可

以n=5621为例,
先令num=n,并且转换为字符串便于处理,

从右往左遍历,
i=3时,(2>1),则wei=i=3,同时n[i-1]--,得到临时的num
(其中的'.'代表'9',下同)

num=561.

i=2时,(6>1),则wei=i=2,同时n[i-1]--,得到临时的num

num=55..

i=1时,(5<=5),wei不变,num不变

num=55..

最后,将num从wei(wei=2)处向右的所有字符变为9,即为答案。

参考《代码随想录》中的写法,代码如下:

代码实现:

class Solution
{
public:
    int monotoneIncreasingDigits(int n)
    {
        string s = to_string(n);
        int len = s.size();
        int wei = len; // 从哪里开始不合理,则后面的全变为'9'
        for (int i = len - 1; i > 0; i--)  //从后往前遍历
        {
            if (s[i] < s[i - 1])
            {
                wei = i;
                s[i - 1]--;
            }
        }
        for (int i = wei; i < len; i++)
            s[i] = '9';
        return stoi(s);
    }
};

时间复杂度

O(n)

补充

为什么从右往左遍历而非从左往右遍历,可以简单地从逻辑分析出来:
既然是找最大的num,则优先从数字的低位开始变换,最后得到的结果才会尽可能大。
并且整个过程会非常顺畅,扫描一遍就行。

例如,n=332
如果从左往右进行变化,
则num会先变为num=329,
后2位好不容易符合题意了,但是由于最高位的3与次高位的2不符合大小关系,
因此此时的num是不符合题意的,
而由于采用了从左往右遍历的方式,
导致我们需要从左到右重新扫描一遍
再得到num=299。
因此会比较麻烦,时间复杂度会更高一些。

所以推荐从右往左遍历。

posted @ 2024-11-20 14:44  HB_Computer  阅读(24)  评论(0)    收藏  举报