https://leetcode-cn.com/problems/k-th-smallest-in-lexicographical-order/
给定整数 n
和 k
,找到 1
到 n
中字典序第 k
小的数字。注意:1 ≤ k ≤ n ≤ 10^9。
输入:
n: 13 k: 2
输出:
10
解释:
字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。
求字典序第k个就是上图前序遍历访问的第k节点!但是不需要用前序遍历,如果我们能通过数学方法求出节点1和节点2之间需要走几步,减少很多没必要的移动。
只需要按层节点个数计算即可,
所以节点1到节点2需要移动 1 + 4 = 5 步
https://leetcode-cn.com/problems/k-th-smallest-in-lexicographical-order/solution/shi-cha-shu-by-powcai/
class Solution:
def findKthNumber(self, n, k):
# 计算移动步数
def cal_steps(n, first, last):
step = 0
while first <= n: # 比如n=13
step += min(n + 1, last) - first
# min(13 + 1, 2) - 1 = 1
# min(13 + 1, 20) - 10 = 4
first *= 10
last *= 10
return step # 从节点1到节点2需要移动 1 + 4 = 5 步
cur = 1 # cur设置为1,因为k从1开始
k -= 1 # 扣除掉第一个0节点
while k > 0:
steps = cal_steps(n, cur, cur + 1)
# 当移动步数小于等于k,说明需要向右节点移动,图中就是节点1移动到节点2
# 第k个数不在以cur为根节点的树上
if steps <= k:
k -= steps
cur += 1 # cur在字典序数组中从左往右移动
# 当移动步数大于k,说明目标值在节点1和节点2之间,要向下移动!即从节点1移动到节点10
else: # 在子树中
k -= 1 # 刨除根节点
cur *= 10 # cur在字典序数组中从上往下移动
return cur
https://leetcode-cn.com/problems/k-th-smallest-in-lexicographical-order/solution/yi-tu-sheng-qian-yan-by-pianpianboy/