题目描述
解题思路
有一说一,这题用树的方式很容易理解,想象有如下一棵树
我们要求第k小的树,也就是求这样一个节点:以从上到下从左到右遍历这棵树它是第k个。因为如上所示的这棵树它从上到下从左到右遍历也就是字典序。所以我们可以按如下的步骤进行
- 从最顶上的节点出发,从左往右计算以每个子节点为前缀的数字个数 n u m num num
- 如果 n u m num num比k大,那么说明深度太浅了,我们将 n u m num num*10,也就是将其向下移动一层,深度++
- 如果 n u m num num比k小,说明子树所处的位置太左了,我们将 n u m num num+1,也就是将子树往右移一个
参考代码
//用来求以pre为前缀的数字个数,next为下一前缀,要注意这里next要为long long,不然一直*10会溢出int上界
int getPre(int pre, int n){
int count = 0;
long long pr = pre;
long long next = pr + 1;
while(pr <= n){
count += min(next, (long long) n + 1) - pr;
pr *= 10;
next *= 10;
}
return count;
}
class Solution {
public:
int findKthNumber(int n, int k) {
int pre = 1;
int flag = false;
k--;
while(k){
int num = getPre(pre, n);
if(num > k) {
pre *= 10;
k--;
}
else {
pre++;
k -= num;
}
}
return pre;
}
};