LeetCode:386. Lexicographical Numbers & 440. K-th Smallest in Lexicographical Order
这一题自己始终做不出来,而且找不出来错误在哪儿(这是致命的),但是看了答案又觉得很简单。
自己的思路是这样:
对于一个数,压进去自己之后,再去看它的十倍,对它进行dfs。返回之后再对本身进行往上加,然后dfs:
class Solution {
public:
vector<int> lexicalOrder(int n) {
vector<int> ret;
helper(1, n, ret);
return std::move(ret);
}
private:
void helper(int tempNum, int maxNum, vector<int>& ret) {
if (ret.size() == maxNum)
return;
if (tempNum > maxNum)
return;
if (tempNum <= maxNum)
ret.push_back(tempNum);
helper(tempNum*10, maxNum, ret);
int cnt = 1;
while (ret.size() < maxNum) {
helper(tempNum + cnt, maxNum, ret);
++cnt;
}
}
};
报的错误是超时,应该是陷入死循环。可能代码写的有问题,但是感觉思路应该是没错的,所以以后有机会按照这个思路写一下吧。
然后再说从评论区看来的答案,就很简洁明了了:
我们只是对每个数字在它们后面添加从0到9,形成树,然后再去前序遍历,所以:
class Solution {
public:
vector<int> lexicalOrder(int n) {
vector<int> ret;
for (int i = 1; i < 10; ++i)
dfs(ret, i, n);
return ret;
}
private:
void dfs(vector<int>& ret, int temp, int maxNum) {
if (temp > maxNum)
return;
ret.push_back(temp);
for (int i = 0; i < 10; ++i)
dfs(ret, temp*10+i, maxNum);
}
};
相比之下,自己的思路确实有点复杂了。
然后还有一个迭代的方法,但是有点难以理解,代码先放在这儿,以后再理解吧:
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;
}
};
另外一道相关的题目:
这是当时找实习的时候,头条一面给我出的题。虽然是hard题,但是如果我做出上面的medium方法的话,应该就可以过关了,虽然会超时:
class Solution {
public:
int findKthNumber(int n, int k) {
int retNum = -1;
int cnt = k;
for (int i = 1; i < 10; ++i) {
dfs(i, n, retNum, cnt);
if (retNum != -1)
return retNum;
}
return retNum;
}
private:
void dfs(int tempNum, int maxNum, int& retNum, int& cnt) {
if (tempNum > maxNum)
return;
--cnt;
if (cnt == 0) {
retNum = tempNum;
return;
}
for (int i = 0; i < 10; ++i) {
dfs(tempNum*10 + i, maxNum, retNum, cnt);
if (retNum != -1)
return;
}
}
};
然后下面这个方法没有完全理解,自己写肯定写不出来,之后再理解吧:
public int findKthNumber(int n, int k) {
int curr = 1;
k = k - 1;
while (k > 0) {
int steps = calSteps(n, curr, curr + 1);
if (steps <= k) {
curr += 1;
k -= steps;
} else {
curr *= 10;
k -= 1;
}
}
return curr;
}
//use long in case of overflow
public int calSteps(int n, long n1, long n2) {
int steps = 0;
while (n1 <= n) {
steps += Math.min(n + 1, n2) - n1;
n1 *= 10;
n2 *= 10;
}
return steps;
}