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