LeetCode/solutions/386. Lexicographical Numbers.md
2019-12-20 14:37:30 +08:00

2.6 KiB
Raw Blame History

386. Lexicographical Numbers

思路

题目给定一个n要求将1~n所有数字按照字典序排序。

暴力解法就是用STL的sort函数然后自定义cmp函数此时时间复杂度为O(nlogn)。但很明显我们可以直接从前往后按照字典序写出来,所以时间复杂度可以是线性的。

思路一、递归

想象一下我们该怎样按照字典序将结果写出来假设n = 119

初始时为1到9           : 1                                                       2         3 ...  9
在上一层每个数后面添加0-9:   10                  11                 12  13 ... 19    20...29   ...    90...99
在上一层每个数后面添加0-9:       100,101,...,109    110,111,...,119 

最终得到的数组          : 1 10 100 101 ...   

所以这可以用递归实现大致思路就是每次将一个数push进结果数组中后都要不断尝试在其后添0-9详见代码。

时间复杂度O(n)

思路二、迭代

也可将上述过程写成迭代的形式用一个1到n的for循环用cur表示当前应该填入res[i]的值初始为1。关键在于如何更新cur:

  • 如果cur后面添加一个0后没有超过n, 那么在cur后面添加一个0再进入下一循环即可
  • 否则
    • 如果cur本身就不小于n了那么应该先将其除10在上图相当于回到上一层例如119 -> 11
    • 将cur加1如果加1后产生了很多0即遇到了进位如109 -> 110则应该不断除0直到末尾不是0。

时间复杂度O(n)空间复杂度O(n)

C++

思路一

class Solution {
private:
    void helper(int num, int n, vector<int> &res){
        res.push_back(num);
        // 在后面分别添加0-9然后进入递归
        for(int i = 0; i < 10; i++){
            int tmp = num*10 + i;
            if(tmp > n) return;
            helper(tmp, n, res);
        }
    }
public:
    vector<int> lexicalOrder(int n) {
        vector<int>res;
        // 初始时为1到9
        for(int i = 1; i <= min(9, n); i++)
            helper(i, n, res);
        
        return res;
    }
};

思路二

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;
    }
};