貪心——738.單調遞增的數字

給定一個非負整數 N,找出小於或等於 N 的最大的整數,同時這個整數需要滿足其各個位數上的數字是單調遞增。

(當且僅當每個相鄰位數上的數字 x 和 y 滿足 x <= y 時,我們稱這個整數是單調遞增的。)

示例 1:

  • 輸入: N = 10
  • 輸出: 9

示例 2:

  • 輸入: N = 1234
  • 輸出: 1234

示例 3:

  • 輸入: N = 332
  • 輸出: 299

說明: N 是在 [0, 10^9] 範圍內的一個整數。

 

首先把數字n按位,從小到大(從後往前)處理成list:

1         List<Integer> list = new ArrayList<>();
2         while (n >= 1) {
3             list.add(n % 10);
4             n /= 10;
5         }

 

將當前的數n處理成比n小的最大「遞增數「,關鍵就在於位數上的遞增。

從n的每一位數從高到低來說,如果當前要比較的數字[index]和遍歷到的數字[i]:

  • 大於:當前數字元合遞增要求,
    index = i--;
  • 等於:當前數字無法判斷,需要遍歷下一位數:
    i--;
  • 小於:
    • 當前位數夠減一:直接減
    • 當前位數不夠減:向前借位直到
      • 夠減一
      • 第一位數(第一位數 >= 1,肯定夠)

 

程式碼如下:

 1 class Solution {
 2     public int monotoneIncreasingDigits(int n) {
 3         List<Integer> list = new ArrayList<>();
 4         while (n >= 1) {
 5             list.add(n % 10);
 6             n /= 10;
 7         }
 8         //count == 位數,index == 判斷的位數
 9         int count = list.size(), index = count - 1, i = count - 2;
10         while (i >= 0) {
11             if (list.get(i) > list.get(index)) {
12                 index = i--;
13             } else if (list.get(i) < list.get(index)) {
14                 //向前借位(可向前0位),直到當前數字夠-1 or 到了第一位(借位到了第一位,第一位數字必定 >= 1,肯定夠)
15                 while (list.get(index) == 0 && index > 0) {
16                     --index;
17                 }
18                 //當前位數-1
19                 list.set(index, list.get(index)-1);
20                 //從-1位數的後一位開始,每一位數都是9
21                 --index;
22                 while (index >= 0) {
23                     list.set(index--, 9);
24                 }
25                 break;
26             } else {
27                 --i;
28             }
29         }
30         
31         int result = 0, base = 1;
32         i = 0;
33         while (i < count) {
34             result += list.get(i++) * base;
35             base *= 10;
36         }
37         return result;
38     }
39 }

時間:O(n)

空間:O(1)(除了返回值無須額外空間)

Tags: