440. 字典序的第K小数字(极难,需复盘)

299 篇文章 1 订阅
227 篇文章 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。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/k-th-smallest-in-lexicographical-order
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

本题极难,但是是面试考察的点,需要熟练掌握,首先缕清思路把:

题目中要求找到字典序不大于 n 的第 k 个数字,我们知道字典序的排序是类似树形结构的,如图:

在这里插入图片描述

1 是最小的,第二小的是 10,然后是 100,有点类似二叉树的先序遍历,那么,在范围 n 内,如何确定节点呢?

拿 1 分析,如果此时需要找到小于 102 的第 10 个结点,如果判断 1 是往下走到 10,还是往右走到 2,我们只需要判断 在小于 102 的树中,处在 1 下面的节点的个数,如果节点个数大于 k,说明第 k 各节点是在 1 的下面,否则是在 1 的右边,如代码:

 while (k > 0) {
            long nodes = getNodes(n, cur);
            if (nodes > k) {// 当前树节点大于 k,说明在下面,k--,cur 乘以 10
                k--;
                cur *= 10;
            } else {// 反之,在右边的树,k -= nodes,cur 加一
                k -= nodes;
                cur++;
            }
        }

具体看注释:

然后题目的难点,就在于如何判断当前树下面有多少节点?

还是之前的例子分析把

在这里插入图片描述
如果想看 1 下面有少个节点小于等于 102,只需要让 1 加上每一层的节点个数,需要定义一个变量,指向下一个峰,也就是 2,此时第一层的节点个数就是 next - cur = 1 个,此时 cur 等于 1,n = 102,所以继续加下一层的节点个数

下一个峰是 20,节点个数是 next * 10 - cur * 10,等于 10,此时 cur 等于 10,继续加下一层,此时按照规律,下一层个数应该是 100,但是到 102 就截止了,次层数的节点是 n - cur + 1 个,所以,每次需要使用 Math.min 判断最小的数值是满足层数节点的。

本题难就难在一个思维,整体代码看起来没几行,挺简单的,但是分析起来确实复杂,本题需多次复盘

还有一个坑,本题 n 的范围到 10 的 9 次方,超过 int 的范围了,所以要使用 long 变量

class Solution {
    public int findKthNumber(int n, int k) {
    	long cur = 1;
        k--;
        while (k > 0) {
            long nodes = getNodes(n, cur);
            if (nodes > k) {
                k--;
                cur *= 10;
            } else {
                k -= nodes;
                cur++;
            }
        }
        return (int) cur;
    }
    public int getNodes(int n, long cur) {
        long totalNodes = 0;
        long next = cur + 1;
        while (cur <= n) {
            totalNodes += Math.min(next - cur, n - cur + 1);
            next *= 10;
            cur *= 10;
        }
        return (int)totalNodes;
    }
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_努力努力再努力_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值