[Leetcode] 440. K-th Smallest in Lexicographical Order 解题报告

来源:互联网 发布:上海 微软云计算架构师 编辑:程序博客网 时间:2024/06/06 13:04

题目

Given integers n and k, find the lexicographically k-th smallest integer in the range from 1 to n.

Note: 1 ≤ k ≤ n ≤ 109.

Example:

Input:n: 13   k: 2Output:10Explanation:The lexicographical order is [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9], so the second smallest number is 10.

思路

这道题目的难度为hard,确实是有道理的。我这里参考了http://www.cnblogs.com/grandyang/p/6031787.html上面的解法。具体分析如下:

我们需要找出能够快速定位第k大的数的方法,仔细观察字典顺序的数组我们可以发现:其实这是个十叉树Dennary Tree,就是每个节点可以最多有10个子节点,比如数组1的子节点就是10到19,数字10的子节点可以是100到109。但是由于n大小的限制,我们所构成的并不是一个满十叉树。分析题目中给出的例子就可以知道,数字1的子节点有4个(10,11,12,13),而后面的数字2到9都没有子节点,那么这道题目实际上就变成了一个先序遍历十叉树的问题了,此时难点就变成了如何计算出每个节点的子节点的个数。我们不停用k去减去子节点的个数,当k减到0的时候,当前位置即为所求。

现在我们来看如何求子节点个数,比如数字1和数字2,我们要求按字典遍历顺序从1到2需要经过多少个数字,首先把1本身这一个数字加到step中,然后我们把范围扩大十倍,范围编程10到20之间,但是由于我们要考虑n的大小,由于n为13,所以只有4个子节点,这样我们就知道从数字1遍历到数字2需要经过5个数字,然后我们看step是否小于等于k:如果是,则cur自增1,k减去step;如果不是,说明要求的数字在子节点中,我们此时cur乘以10,k自减1,以此类推,直到k为0退出循环,此时cur即为所求。

代码

class Solution {public:    int findKthNumber(int n, int k) {        int cur = 1;        --k;        while (k > 0) {            long long step = 0, first = cur, last = cur + 1;            while (first <= n) {                step += min((long long)n + 1, last) - first;                first *= 10;                last *= 10;            }            if (step <= k) {                ++cur;                k -= step;            } else {                cur *= 10;                --k;             }        }        return cur;    }};

阅读全文
0 0
原创粉丝点击