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


    Q:给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字。
    注意:(1 ≤ k ≤ n ≤ 10^9)

    示例 :
    输入:
    n: 13 k: 2
    输出:
    10
    解释:
    字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。

    A:
    1.用回溯法做

        private int count;
        private int res;
    
        public int findKthNumber(int n, int k) {
            count = k;
            res = -1;
            dfs(0, n);
            return res;
        }
    
        private void dfs(int i, int n) {
            if (i > n || res != -1)
                return;
            if (i != 0) {
                count--;
                if (count == 0) {
                    res = i;
                }
            }
            for (int j = 0; j <= 9; j++) {
                int curr = 10 * i + j;
                if (curr != 0)
                    dfs(curr, n);
            }
        }
    

    然后我就超时了……赤裸裸的超时了……
    2.dfs剪枝(感谢@jiaxin)
    最大的亮点在于观察上下界去计算每层的node数量,进而减少重复计算。我们可以建立一个字典树一样的结构。思路就是遍历了,但是每个都遍历不现实,所以我们不妨去计算一下他在哪个node对应的集合中。
    我们可以先算出来这个数值在第一层哪个node集合里面,再去看对应第二层的哪个node集合,最后找到那个走了k步的node 就是我们的答案了。
    下面说node集合数量怎么计算:

    通过图我们会发现每层的node他的上界实际是下一个node对应层的最小值。所以计算该层node数量只需要 ((curr+1)*10-curr*10)就好,但是他还有一个上界就是最大值。
    故每层的数量就是 (min((curr+1)*10,max\_value+1)-curr*10);计算这个node 有多少节点就把符合条件的每一层加起来就好

    代码:

        public int findKthNumber(int n, int k) {
            int prefix = 1;
            k--;//k记录要找的数字在prefix后的第几个
            while (k > 0) {
                long cnt = getCnt(n, prefix, prefix + 1);// 当前prefix下有多少个元素;包含prefix
                if (cnt <= k) {// 向右
                    k -= cnt;
                    prefix++;
                } else {// 向下
                    k--;
                    prefix *= 10;
                }
            }
            return prefix;
        }
    
        private long getCnt(long n, long n1, long n2) {//这边用long,如果有int,有可能会超
            long cnt = 0;
            while (n1 <= n) {
                cnt += Math.min(n + 1, n2) - n1;
                n1 *= 10;
                n2 *= 10;
            }
            return cnt;
        }
    
  • 相关阅读:
    迪杰斯特拉算法
    基数排序
    快排算法
    插入排序与希尔排序算法
    java--jmm知识
    Java基础
    socket代理
    TestLink 学习第一周
    软件体系结构第三章之解释器风格
    如何衡量个人在各自团队的效率和绩效
  • 原文地址:https://www.cnblogs.com/xym4869/p/12787097.html
Copyright © 2020-2023  润新知