力扣-738. 单调递增的数字

1.题目

题目地址(738. 单调递增的数字 - 力扣(LeetCode))

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

题目描述

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

给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增

 

示例 1:

输入: n = 10
输出: 9

示例 2:

输入: n = 1234
输出: 1234

示例 3:

输入: n = 332
输出: 299

 

提示:

  • 0 <= n <= 109

2.题解

2.1 贪心算法

思路

首先我们从高位到低位,尽可能的使结果与初始值n相同(对应位数值相同)
当遇到第一个不能满足递增条件的位i时(nums[i-1] > nums[i]),我们回退到i-1, 并将该位数值-1,
此时不管后面的位数值为多少,都肯定是满足 结果<初始值,为了争取最大值,我们可以将后面所有值设置为9, 比如像234999(235->234,后面999) < 235212

但是还需要注意的是,由于这里我们将nums[i] -= 1, 回退了一个数字,可能导致之前满足的递增序列不再成立,所以我们需要进行回溯
比如像: 232999(233 -> 232) < 233211, 但是这里232已经不满足递增序列了
所以我们要继续回溯 229999 < 232999 < 233211 (23 -> 22),
且由于原先的数列是递增数列,这里nums[i]--导致递增不满足,也只会是数值相差1的这一种情况(所以回溯过程中只要进行nums[i - 1] -= 1;即可,不需要考虑具体回溯多少)

可以发现,我们只要进行回溯,判断在尽可能贴近原数值的情况下,确定最后一个满足递增序列的位置i即可,[0,i]保持原数值,[i+1,len)选择'9'

代码

  • 语言支持:C++

C++ Code:

class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string nums = to_string(n), ans;
        int i = 1, len = nums.length();
        while (i < len && nums[i - 1] <= nums[i])
            i++;
        // 说明中途暂停了,有不满足的条件, 有nums[i-1] > nums[i]
        if (i < len) {
            while (i > 0 && nums[i - 1] > nums[i]) {
                nums[i - 1] -= 1;
                i--;
            }
            // 此时又回到了nums[i - 1] <= nums[i], i之后的所有都不满足,直接改为9即可
            while (++i < len)
                nums[i] = '9';
        }
        int num = stoi(nums);
        return num;
    }
};

复杂度分析

令 n 为数组长度。

  • 时间复杂度:\(O(n)\)
  • 空间复杂度:\(O(n)\)
posted @ 2024-06-21 02:36  DawnTraveler  阅读(8)  评论(0编辑  收藏  举报