diff --git a/solutions/386. Lexicographical Numbers.md b/solutions/386. Lexicographical Numbers.md new file mode 100644 index 0000000..85087f9 --- /dev/null +++ b/solutions/386. Lexicographical Numbers.md @@ -0,0 +1,78 @@ +# [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 &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 lexicalOrder(int n) { + vectorres; + // 初始时为1到9 + for(int i = 1; i <= min(9, n); i++) + helper(i, n, res); + + return res; + } +}; +``` + +## 思路二 +``` C++ +class Solution { +public: + vector lexicalOrder(int n) { + vector 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; + } +}; +```