使用字典序排数的暴力解法会提示超时
class Solution {
public int findKthNumber(int n, int k) {
//起始位置cur 为1 , k为0
long cur = 1; // 当前遍历到的数字,从1(根)出发
k = k - 1; // 从1出发开始往后按字典序从小到大的顺序走k-1步到达的就是 字典序的第K小数字
while(k > 0){
int nodes = getNodes(n, cur);
//要走的步数k等于nodes数时,cur要向旁边子树移动
//nodes可以理解为元素从1开始的数组,k可以理解为索引 从0开始
if(k >= nodes){ // 向右侧节点走:字典序上升nodes位
k = k - nodes;
cur++; // 当前数字 cur = cur + 1
}else{ // 向下往最左孩子节点走:字典序上升1位
k = k - 1;
cur *= 10; // 当前数字 cur = cur * 10
}
}
return (int)cur; // 最后cur停在的数字就是字典序的第K小数字
}
// 计算以cur为根的子树节点数目,所有节点的值必须 <= n
//cur用int会超出最大值 , 用long
private int getNodes(int n, long cur){
long next = cur + 1; // 当前节点右侧右边节点的值
long totalNodes = 0; // 记录子树中的全部节点数目
//cur等于n时也应该进入循环, 因为有一个元素
while(cur <= n){
totalNodes += Math.min(n - cur + 1, next - cur);
next *= 10;
cur *= 10;
}
return (int)totalNodes;
}
}