D22 LeetCode 440.字典序的第K小数字(困难)

一、题目

二、思路(自己)

  • 题目要求是字典序排列,即按照字符串比较一样进行排列,前几天刚好面过类似的题,为了降低时间复杂度,我们可以采用红黑树进行排序。
  • 使用TreeSet来存储里面的数组,重写比较器即可。
class Solution {
   public int findKthNumber(int n, int k) {
        Set<Integer> set=new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                String s1=o1+"";
                String s2=o2+"";
                return s1.compareTo(s2);
            }
        });
        for (int i = 1; i <=n ; i++) {
            set.add(i);
        }
        Integer[] a=new Integer[n];
        set.toArray(a);
        return a[k-1];
    }
}

  •  这么写时间复杂度还是高了,我觉得用红黑树没错,不过后面可能有点问题。
class Solution {
   public int findKthNumber(int n, int k) {
        Set<Integer> set=new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                String s1=o1+"";
                String s2=o2+"";
                return s1.compareTo(s2);
            }
        });
        for (int i = 1; i <=n ; i++) {
            set.add(i);
        }
//        Integer[] a=new Integer[n];
//        set.toArray(a);
//        return a[k-1];
        List<Integer> list=new ArrayList<>(set);
        return list.get(k-1);
    }
}
  • 把后面取指定元素转换为list还是超出时间限制,说明此题不是用红黑树解。说明题解的解法比O(n)还小。

三、题解(官方)

  • 官方题解就是给力,真的挺难想到的。我按照自己的理解加了注释
class Solution {
   public int findKthNumber(int n, int k) {
            int curr = 1;
            k--;
            while (k > 0) {
                int steps = getSteps(curr, n);
                if (steps <= k) {
                    //如果以curr为首的数字数量小于k
                    k -= steps;
                    curr++;
                } else {
                    //以curr为首的数字数量大于k,k已经减去之前小于的数量了,当k为0时即已经找到了
                    curr = curr * 10;
                    k--;
                }
            }
            return curr;
        }

        //获取curr为根节点的树的子节点数量
        public int getSteps(int curr, long n) {
            int steps = 0;
            long first = curr;
            long last = curr;
            while (first <= n) {
                steps += Math.min(last, n) - first + 1;
                first = first * 10;
                last = last * 10 + 9;
            }
            return steps;
        }
    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值