您的位置:首页 > 其它

[Leetcode] 386. Lexicographical Numbers 解题报告

2017-09-04 12:53 411 查看
题目

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 (
ad2e
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);
}
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: