转载 :
https://zhuanlan.zhihu.com/p/113194071
题目描述:
给定整数 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。
思路:
十叉树,用题目的测试用例来举例子。
我们求字典序第k个就是上图前序遍历访问的第k节点!但是不需要用前序遍历,如果我们能通过数学方法求出节点1和节点2之间需要走几步,减少很多没必要的移动。
其实只需要按层节点个数计算即可,图中节点1和节点2在第二层,因为n = 13,节点1可以移动到节点2(同一层)所以在第二层需要移动1步。
第三层,移动个数就是 (13 - 10 + 1) = 4 (min(13 + 1, 20) - 10)
所以节点1到节点2需要移动 1 + 4 = 5 步
当移动步数小于等于k
,说明需要向右节点移动,图中就是节点1移动到节点2。
当移动步数大于k
,说明目标值在节点1和节点2之间,我们要向下移动!即从节点1移动到节点10。
代码:
class Solution:
def findKthNumber(self, n: int, k: int) -> int:
def cal_steps(n, n1, n2):
step = 0
while n1 <= n:
step += min(n2, n + 1) - n1
n1 *= 10
n2 *= 10
return step
cur = 1
k -= 1
while k > 0:
steps = cal_steps(n, cur, cur + 1)
if steps <= k:
k -= steps
cur += 1
else:
k -= 1
cur *= 10
return cur