题目描述
给定整数 n 和 k,返回 [1, n] 中字典序第 k 小的数字。
样例描述
示例 1:
输入: n = 13, k = 2
输出: 10
解释: 字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。
示例 2:
输入: n = 1, k = 1
输出: 1
思路
回溯(类似树前序) + 剪枝
- 模拟树中前序遍历,让当前cur走k - 1步就是目标位置,根据求当前cur根所在树的所有结点判断下一步的方向
代码
class Solution {
public int findKthNumber(int n, int k) {
long cur = 1;
//从1开始,走k - 1步找到第k - 1小的
k = k - 1;
//只要没走完k - 1步就不断递归
while (k > 0) {
//获取以cur为根结点的树的所有结点个数
long nodes = getNodes(n, cur);
//如果k大于这个数,说明不在以cur为跟的结点,往右边结点走
if (k >= nodes) {
//走过的步数为左边所有结点个数
k -= nodes;
cur ++;
} else {
//在的话,就往下走,cur每次指向当前层最左边的结点
k --;
cur *= 10;
}
}
return (int)cur;
}
public long getNodes(int n, long cur) {
long res = 0;
//next是cur右边结点,每次指向右边层的第一个
long next = cur + 1;
while (cur <= n) {
//右边层第一个(编号)减去左边层第一个,就是左边的所有个数
//注意防止越界,最大为n,cur不能超过n
res += Math.min(n - cur + 1, next - cur);
//同时往下走
cur *= 10;
next *= 10;
}
return res;
}
}