牛客234288题:用前缀树遍历思想解决字典序第K小问题

一、题目解读
题目要求在字典序排列的1~n数字序列中,快速找到第k个数字。字典序的特殊性使得直接排序会超时,需采用前缀树遍历的数学方法优化时间复杂度至O(log²n)。
二、解题思路
核心采用前缀计数法:
将数字视为前缀树,如"1"为根节点,"10~19"为其子节点
通过计算每个前缀覆盖的数字范围(如前缀"1"覆盖1,10~19,100~199...)
动态调整搜索路径:若k大于当前前缀覆盖范围,则横向移动;否则纵向深入子节点
三、解题步骤
初始化:当前前缀curr=1,k需减1适配0-based计数
范围计算:
路径选择:
当steps≤k时横向移动(curr++)
否则纵向深入(curr*=10)并减少k计数
四、完整代码实现
class Solution {
public:
int findKth(int n, int k) {
int curr = 1;
k--; // 初始化为第一个数1
while (k > 0) {
long steps = 0;
long first = curr;
long last = curr + 1;
// 计算以curr为前缀的数字个数
while (first <= n) {
steps += min((long)n + 1, last) - first;
first *= 10;
last *= 10;
}
if (steps <= k) {
// 不在当前前缀子树中
curr++;
k -= steps;
} else {
// 在当前前缀子树中
curr *= 10;
k--;
}
}
return curr;
}
};五、总结
该算法巧妙利用字典序的树形特性,通过数学计算替代暴力排序。关键点在于:
前缀范围计算的准确性
横向/纵向移动的条件判断
时间复杂度优化至对数级别
原创内容 转载请注明出处
