[LeetCode] K-th Smallest in Lexicographical Order 字典順序的第K小數字


 

Given integers n and k, find the lexicographically k-th smallest integer in the range from 1 to n.

Note: 1 ≤ k ≤ n ≤ 109.

Example:

Input:
n: 13   k: 2

Output:
10

Explanation:
The lexicographical order is [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9], so the second smallest number is 10.

 

這道題是之前那道Lexicographical Numbers的延伸,之前讓按字典順序打印數組,而這道題讓我們快速定位某一個位置,那么我們就不能像之前那道題一樣,一個一個的遍歷,這樣無法通過OJ,這也是這道題被定為Hard的原因。那么我們得找出能夠快速定位的方法,我們如果仔細觀察字典順序的數組,我們可以發現,其實這是個十叉樹Denary Tree,就是每個節點的子節點可以有十個,比如數字1的子節點就是10到19,數字10的子節點可以是100到109,但是由於n大小的限制,構成的並不是一個滿十叉樹。我們分析題目中給的例子可以知道,數字1的子節點有4個(10,11,12,13),而后面的數字2到9都沒有子節點,那么這道題實際上就變成了一個先序遍歷十叉樹的問題,那么難點就變成了如何計算出每個節點的子節點的個數,我們不停的用k減去子節點的個數,當k減到0的時候,當前位置的數字即為所求。現在我們來看如何求子節點個數,比如數字1和數字2,我們要求按字典遍歷順序從1到2需要經過多少個數字,首先把1本身這一個數字加到step中,然后我們把范圍擴大十倍,范圍變成10到20之前,但是由於我們要考慮n的大小,由於n為13,所以只有4個子節點,這樣我們就知道從數字1遍歷到數字2需要經過5個數字,然后我們看step是否小於等於k,如果是,我們cur自增1,k減去step;如果不是,說明要求的數字在子節點中,我們此時cur乘以10,k自減1,以此類推,直到k為0推出循環,此時cur即為所求:

 

class Solution {
public:
    int findKthNumber(int n, int k) {
        int cur = 1;
        --k;
        while (k > 0) {
            long long step = 0, first = cur, last = cur + 1;
            while (first <= n) {
                step += min((long long)n + 1, last) - first;
                first *= 10;
                last *= 10;
            }
            if (step <= k) {
                ++cur;
                k -= step;
            } else {
                cur *= 10;
                --k; 
            }
        }
        return cur;
    }
};

 

類似題目:

Lexicographical Numbers

 

參考資料:

https://discuss.leetcode.com/topic/64624/concise-easy-to-understand-java-5ms-solution-with-explaination/2

https://discuss.leetcode.com/topic/64462/c-python-0ms-o-log-n-2-time-o-1-space-super-easy-solution-with-detailed-explanations

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM