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

79 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [386. Lexicographical Numbers](https://leetcode.com/problems/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++
## 思路一
``` 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;
}
};
```
## 思路二
``` C++
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;
}
};
```