美文网首页
LeetCode#440字典序的第k小数字

LeetCode#440字典序的第k小数字

作者: Android_ZzT | 来源:发表于2019-08-29 17:41 被阅读0次

    input

    • n:数字大小
    • k:第k个小的数

    example

    input: (13,2)
    output: 10
    reason: [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],10是第2小的数字

    思路

    • 理解数字的字典序,可以理解为一颗十叉树,根为1,子节点为10-19,根为2,子节点为20-29
    • 输入k,可理解为要在数组中走的步数
    • 定义5个变量,result = 1 最终结果;lastSteps = k -1 表示剩余步数;left = result 左节点;right = result+1 右节点; count = 0 记录需要跨过的节点数
    • 先寻找最终走到终点的范围在哪,也就是找到不满的十叉树的根节点是谁
    • 当 left <= n 时,证明最终位置在当前节点的右边或者下边
    • 如果 right 比 n + 1 小,left right 各向下一层继续找,同时累计 count += min(right, n+1) - left
    • 直到 left 大于 n,将累加的节点和当前剩余步数相比较
    • 如果 lastSteps > count,证明 left 的子节点能全部走完,所以需要向右走一步 lastSteps -= count; result += 1;
    • 如果 lastSteps <= count,证明 left 的子节点已经足够走完剩余的步数了,这时向下走一步,lastSteps--; result*=10;
    • 当剩余步数为0时,result 就是最终结果

    代码

    class Solution {
        public void int findKthNumber(int n, int k) {
            int result = 1;
            int lastSteps = k - 1; //默认走了一步,走到第一个数
            while (lastSteps > 0) {
                long left = result; //用 long 类型,防止 n 达到 2的32次方附近时,left * 10 会溢出
                long right = result + 1;
                int count = 0;
                while(left <= n) { //向下或向右探索,计算需要跨过的节点数
                    count += Math.min(right, n+1) - left;
                    left *= 10;
                    right *= 10;
                }
                
                if (count > lastSteps) { //节点太多,跨不过去,只能向下走一层
                    lastSteps --;
                    result *= 10;
                } else { //节点不足,当前剩余步数足够走完全部节点,直接跨过这个节点以及他的子节点,向右走一步
                    lastSteps -= count;
                    result ++;
                }
            }
            return result;
        }
    
    }
    

    相关文章

      网友评论

          本文标题:LeetCode#440字典序的第k小数字

          本文链接:https://www.haomeiwen.com/subject/xncwectx.html