1. 程式人生 > >[LeetCode] Lexicographical Numbers 字典順序的數字

[LeetCode] Lexicographical Numbers 字典順序的數字

Given an integer n, return 1 - n in lexicographical order.

For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9].

Please optimize your algorithm to use less time and space. The input size may be as large as 5,000,000.

這道題給了我們一個整數n,讓我們把區間[1,n]的所有數字按照字典順序來排列,題目中也給了我們字典順序的例子。那麼我們需要重新排序,我最開始想到的方法是重寫sort方法的comparator,思路是把所有數字都轉為字串,然後兩個字串按位相比,然後排好序後再轉回數字,這種方法通過不了OJ的大集合,說明本題不是想考我們這種方法。我在論壇裡看到大家普遍使用的是下面這種方法,學習了一下,感覺思路十分巧妙,估計我自己肯定想不出來。這種思路是按個位數遍歷,在遍歷下一個個位數之前,先遍歷十位數,十位數的高位為之前的個位數,只要這個多位數並沒有超過n,就可以一直往後遍歷,如果超過了,我們除以10,然後再加1,如果加1後末尾形成了很多0,那麼我們要用個while迴圈把0都去掉,然後繼續運算,參見程式碼如下:

解法一:

class Solution {
public:
    vector<int> lexicalOrder(int n) {
        vector<int> res(n);
        int cur = 1;
        for (int i = 0; i < n; ++i) {
            res[i] = cur;
            if (cur * 10 <= n) {
                cur *= 10;
            } else {
                
if (cur >= n) cur /= 10; cur += 1; while (cur % 10 == 0) cur /= 10; } } return res; } };

下面這種方法是上面解法的遞迴形式,思路並沒有什麼不同,參見程式碼如下:

解法二:

class Solution {
public:
    vector<int> lexicalOrder(int n) {
        vector<int
> res; for (int i = 1; i <= 9; ++i) { helper(i, n, res); } return res; } void helper(int cur, int n, vector<int>& res) { if (cur > n) return; res.push_back(cur); for (int i = 0; i <= 9; ++i) { if (cur * 10 + i <= n) { helper(cur * 10 + i, n, res); } else break; } } };

參考資料: