给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字。
注意:1 ≤ k ≤ n ≤ 109。
示例 :
输入:
n: 13 k: 2
输出:
10
解释:
字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/k-th-smallest-in-lexicographical-order
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public:
int findKthNumber(int n, int k) {
long p = 1;//作为一个指针,指向当前所在位置,当p==k时,也就是到了排位第k的数
long prefix = 1;//前缀
while(p < k)
{
long count = getCount(prefix, n);//获得当前前缀下所有子节点的个数
if (p + count > k)
{
/// 说明第k个数,在这个前缀范围里面
prefix *= 10;
p++;//把指针指向了第一个子节点的位置,比如11乘10后变成110,指针从11指向了110
}
else if (p + count <= k)
{
/// 说明第k个数,不在这个前缀范围里面,前缀需要扩大+1
prefix++;
p += count;
}
}
return static_cast<int>(prefix);
}
long getCount(long prefix,long n)
{
//prefix是前缀 n是上界
long cur = prefix;
long next = cur + 1;//下一个前缀
long count = 0;
//当前的前缀当然不能大于上界
while(cur <= n)
{
count += min(n+1, next) - cur;//下一个前缀的起点减去当前前缀的起点
cur *= 10;
next *= 10;
// 如果说刚刚prefix是1,next是2,那么现在分别变成10和20
// 1为前缀的子节点增加10个,十叉树增加一层, 变成了两层
// 如果说现在prefix是10,next是20,那么现在分别变成100和200,
// 1为前缀的子节点增加100个,十叉树又增加了一层,变成了三层
}
return count;//把当前前缀下的子节点和返回去
}
};
思路:评论区大佬,没怎么看懂,隔天来。