leetcode440.字典序的第k小数字

1.题目描述

给定整数 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。

2.解题思路

字典序排数可以看做是第一层节点分别为 1-9 的十叉树,然后我们在树上找到第 K 小的数字即可。因此,我们需要分别统计以 1-9 为根节点的每个树的节点个数。如果 K 小于当前树的节点个数,那么第 K 小的数字即在当前树中 (K - 1) ,我们进入子树继续查找;如果 K 大于当前树的节点个数,那么我们需要查找后面树中第 (K - 当前树节点) 小的数字。

其中,比较关键的步骤就是统计树中的节点个数:

首先我们初始化 cur = 1
然后我们让 left = cur,right = cur + 1,此时 right-left 就是第一棵树第一层的节点个数
接下来 left *= 10, right *= 10,这样就进入到了第二层,此时 right-left 就是第二层的节点个数,以此类推直到 left > n
但如果我们是统计 109 以内的字典序,进入第三层时,right 不能指向 200 而只能指向 109,此时 n-left+1 才是当前层的节点个数

假设我们统计完第一棵树的节点数为 node_num,

如果 K >= node_num,我们需要继续向后查找,在后面的树中查找第 K-node_num 小的数字,也即更新 cur += 1
如果 K < node_num,说明第 K 小的数字在子树中,我们需要进入子树继续向下查找,也即更新 cur *= 10
最后当 K=0 时,cur 指向的值即为所求。

3.代码实现

class Solution(object):
    def findKthNumber(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: int
        """
        cur=1
        k-=1
        while k>0:
            left,right=cur,cur+1
            step=0
            while left<=n:
                step+=min(right,n+1)-left
                left*=10
                right*=10
            # 向后查找
            if step<=k:
                k-=step
                cur+=1
            # 进入子树查找
            else:
                k-=1
                cur*=10
        return cur


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值