• LeetCode 386——字典序的第 K 小数字


    1. 题目

    2. 解答

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

    其中,比较关键的步骤就是统计树中的节点个数,我们按照逐层统计的方法来进行,详见下图。

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

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

    • 如果 K >= node_num,我们需要继续向后查找,在后面的树中查找第 K-node_num 小的数字,也即更新 cur += 1
    • 如果 K < node_num,说明第 K 小的数字在子树中,我们需要进入子树继续向下查找,也即更新 cur *= 10

    最后当 K=0 时,cur 指向的值即为所求。

    class Solution {
    public:
        int findKthNumber(int n, int k) {
            
            int cur = 1;
            k--;
            
            while (k > 0)
            {
                long long left = cur;
                long long right = cur + 1;
                int node_num = 0;
                
                while (left <= n) // 统计树中每一层的节点个数
                {
                    node_num += min(right, (long long)(n+1)) - left;
                    left *= 10;
                    right *= 10;
                }
                
                if (node_num <= k) // 向后查找
                {
                    k -= node_num;
                    cur++;
                }
                else // 进入子树查找
                {
                    k--;
                    cur *= 10;
                }
            }
            
            return cur;       
        }
    };
    

    获取更多精彩,请关注「seniusen」!

  • 相关阅读:
    vue.config.js的配置与注释
    Git Pages,使用gh-pages分支显示静态网站
    git subtree 公共仓库
    vue之计算属性
    前端模块化AMD和CMD
    jQuery实现表单全选反选,简洁,好用
    vue之点击切换样式
    vue之本地代理解决跨域问题
    ES6
    jQuery 总结
  • 原文地址:https://www.cnblogs.com/seniusen/p/10607814.html
Copyright © 2020-2023  润新知