天天看點

單調遞增的數字

單調遞增的數字

給定一個非負整數

N

,找出小于或等于

N

的最大的整數,同時這個整數需要滿足其各個位數上的數字是單調遞增。當且僅當每個相鄰位數上的數字

x

y

滿足

x <= y

時,我們稱這個整數是單調遞增的。

示例

輸入: N = 10
輸出: 9
           
輸入: N = 1234
輸出: 1234
           
輸入: N = 332
輸出: 299
           

題解

/**
 * @param {number} N
 * @return {number}
 */
var monotoneIncreasingDigits = function(N) {
    let i = 1;
    let num = N;
    while(i*10 <= num){
        // console.log(i, num);
        // 每次取出兩位
        let n = ~~(num / i) % 100;  
        i = i * 10;
        if(~~(n/10) > n %10) num = ~~(num / i) * i - 1; 
        // 例如 1332 第一次循環之後是 取整(1332 / 10) * 10 - 1 = 1330 - 1 = 1329
        // 第二次循環就是 1300 - 1 = 1299
    }
    return num;
};
           

思路

整體思路就是将數字當作字元串,從尾到頭逆向周遊一遍,每次比較兩位,如果後一個位置上的數小于前一個位置上的數,那麼就将前邊的數減一,并将後邊的所有位都變為

9

,例如當我們周遊到了

1323

中比較

32

的這個位置上,此時

3 > 2

符合條件,那麼我們就将

3

減一并将其後的數都變作

9

,即将其變為

1299

,直到周遊到頭即可。通常來說可以把數字作為字元串來周遊處理,上面的題解是使用純數字的方式去做,首先定義

i

作為标記記錄周遊到到的位置,之後定義

num

作為待處理的數字,定義循環隻要能夠繼續取出兩位數就繼續循環,這是循環的終止條件,此外能夠使用乘法的地方就盡量不要使用除法,在

js

int32

如果不能夠整除則會自動轉雙精度

64

,是以在很多地方都需要強制轉數值為

int32

,之後取出兩位數,這裡

~~

是使用位運算強制轉了整型,在之後将

i * 10

定義到下一位,如果低一位上的值大于大于高一位上的值,那麼就将數值在第

i

位以後的值都變成

,然後減

1

即可達到上述的将此位減

1

以及之後的數字都變為

9

,可以參考上邊的示例,在循環結束後傳回處理的數字即可。

每日一題

https://github.com/WindrunnerMax/EveryDay
           

參考

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