力扣-738. 單調遞增的數字

DawnTraveler發表於2024-06-21

1.題目

題目地址(738. 單調遞增的數字 - 力扣(LeetCode))

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

題目描述

當且僅當每個相鄰位數上的數字 xy 滿足 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)\)

相關文章