1. 程式人生 > >LeetCode筆記:400. Nth Digit

LeetCode筆記:400. Nth Digit

問題:

Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, …

Note:
n is positive and will fit within the range of a 32-bit signed integer (n < 231).

Example 1:

Input:
3

Output:
3

Example 2:

Input:
11

Output:
0

Explanation:
The 11th digit of the sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, … is a 0, which is part of the number 10.

大意:

在無限整數序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, … 中找到第n個數字。

注意:
n是個正數而且會在32位範圍內(n<2的31次方)

例1:

輸入:3
輸出:3

例2:

輸入:11
輸出:0
解釋:序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, … 的第11個數是數字10中的0。

思路:

開始沒看到意思,後來明白了,當序列中的數字是兩位數、三位數等等後,第n個數就不再是序列中的第n個數了,比如10中的1是第10個數字,0是第11個數字。

這麼一來,要找到第n個數,首先要知道這個數所在的序列中的數字是什麼,我們只能先判斷當前的是幾位數,因為每多一位數,其範圍內的數字個數會變成上一輪的10倍,比如個位數有9個,兩位數有90個,三位數有900個。。。兩位數對應的數字有90*2個,三位數有900*3個,所以可以通過這個規律先判斷要找的序列數字是幾位數。

找出是幾位數後,在通過對位數的除法得出數字是多少,比如如果n是12,那麼先通過其大於9,小於90*2+9,得知是兩位數,然後通過(12-9)/2 = 1得出其至少是9+1,也就是10或者10以後的數字,具體是10還是11,要看有沒有餘數,這裡(12-9)%2=1,所以餘數為1,也就是超過了10,是10的後一個數字的第一個數。其實這裡很簡單我們直接就可以知道是11中的第一個1。

如果餘數是0,說明就是當前找到的數字的最後一位,直接將該數字對10取餘即可得到需要的個位數字。如果餘數大於0,說明是下一個序列數字中的數,然後根據餘數來判斷是下個序列數字中的第幾個數。要得到一個多位數中的某位數,有多種做法,一種是化為字元陣列直接取,另一種我用的是先取餘再做除法,比如要得到1245這個數字中的第三個數字4,先讓其對100取餘數得到45,然後對10做觸發得到4。至於怎麼知道是100和10,就可以通過是第幾位來進行10的次方運算了,這個直接看到程式碼就可以明白,只是有點長,要想清楚。

還有一點要注意的是,提交時我在一個很大的數上出了錯,因為題目給的n的範圍是小於2的31次方,這個數字在上述處理過程中可能會有大到超過int型變數範圍的數字,因此不得不全部使用了long型變量表示數字。另外Math.pow()這個次方計算操作的兩個引數必須是double型的,因此也不得不進行了強制轉換又轉換。

程式碼(Java):

public class Solution {
    public int findNthDigit(int n) {
        if (n <= 9) return n;

        long lastNum = 9;
        long reduce = 9;
        long num = 90;
        long i = 2;
        while (n > reduce + num * i) {
            lastNum = lastNum + num;
            reduce = reduce + num * i;
            num = num * 10;
            i++;
        }
        long over = (long)n - reduce;
        System.out.println(lastNum + over / i);
        long index = over / i;
        long reste = over % i;
        if (reste == 0) return (int)((lastNum + index) % 10);
        else return (int)(((lastNum + index + 1) % (long)Math.pow(10.0, (double)(i - reste + 1))) / (long)Math.pow(10.0, (double)(i - reste)));
    }
}