[Leetcode] 386. Lexicographical Numbers 解题报告

来源:互联网 发布:王宝强剧情反转知乎 编辑:程序博客网 时间:2024/05/17 21:50

题目

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.

思路

1、字符串排序:通过观察可以发现,题目所要求的排序刚好是字典序,我们知道字符串的默认比较函数就是字典序,所以可以首先将[1,n]区间内的数都转换为字符串,然后对字符串数组进行排序,最后再转换回来。这种做法思路最简单,时间复杂度是O(nlogn),但是由于字符串和数字之间的转换比较耗时,所以无法通过大数据测试。

2、非递归版本:我们注意到下一个数往往和上一个数有关系:1)如果上一个数小于等于n的十分之一,那么直接给上一个数乘以10构成下一个数;否则,2)如果上一个数的末尾不是9,那么可以直接给上一个数加1构成下一个数;3)如果上一个数的末尾是9,那么就需要给上一个数除以10再加一了。具体见下面的代码。

3、递归版本:非递归版本的思路很复杂,而且也容易出错,其实递归版本的思路非常清晰和简单。通过分析可以发现,我们按照首位可以将数组区分成为9类(首位为1-9),所以依次进行深度优先搜索即可。每次搜索的过程中,在不超过n的情况下,都试图给当前数的后面加上0-9(注意区分和首位的区别)以构成下一个数。深度优先遍历的顺序保证了加入的数字的顺序是正确的。

代码

1、字符串排序:

class Solution {public:    vector<int> lexicalOrder(int n) {        vector<string> tem_res;        for (int i = 1; i <= n; ++i) {            tem_res.push_back(to_string(i));        }        sort(tem_res.begin(), tem_res.end());        vector<int> res;        for (auto val : tem_res) {            res.push_back(stoi(val));        }        return res;    }};

2、非递归版本:

class Solution {public:    vector<int> lexicalOrder(int n) {        if (n < 1) {            return {};        }        vector<int> res(1, 1);        while ( res.size() < n ) {            int last = res[res.size()-1];            if (last * 10 <= n) {               // need to increase the digit count                res.push_back(last * 10);                continue;            }            while ( last != 0 ) {                if ( last % 10 != 9 && last + 1 <= n) {                     res.push_back(last + 1);    // normal increase                    break;                }                last /= 10;            }        }        return res;    }};

3、递归版本:

class Solution {public:    vector<int> lexicalOrder(int n) {        vector<int> res;        for (int i = 1; i < 10; ++i) {            lexicalOrder(i, res, n);        }        return res;    }private:    void lexicalOrder(int num, vector<int> &res, int n) {        if (num > n) {            return;        }        res.push_back(num);        int t = num * 10;        for (int i = 0; i < 10; ++i) {            lexicalOrder(t + i, res, n);        }    }};

原创粉丝点击