zoukankan      html  css  js  c++  java
  • [leetCode]剑指 Offer 40. 最小的k个数

    在这里插入图片描述

    解法一 随机切分

    随机抽取数组中一个元素进行切分并返回该元素下标 index

    • index == k-1
      切分元素正好为第k个元素
    • index < k-1
      第k大的元素在下标为index元素的右边,对index右边的元素进行切分
    • index > k-1
      第k大的元素在下标为index元素的左边,对index左边的元素进行切分
    class Solution {
    
        Random rand = new Random();
    
        public int[] getLeastNumbers(int[] arr, int k) {
            if(arr == null || arr.length == 0 || arr.length < k || k <= 0) 
                return new int[]{};
            int lo = 0;
            int hi = arr.length - 1;
            int index = partition(arr, lo, hi);
            while(index != k - 1){
                if(index > k - 1){
                    hi = index - 1;
                    index = partition(arr, lo, hi);
                }else if(index < k - 1){
                    lo = index + 1;
                    index = partition(arr, lo, hi);
                }
            }
            return Arrays.copyOfRange(arr, 0, k);
        }
    
        /**
        *   随机切分函数
        */
        private int partition(int[] a, int lo, int hi){
            if(a == null || a.length == 0 || lo < 0 || hi > a.length)
                throw new RuntimeException("Invalid Parameters");
            int index = randRange(rand, lo, hi+1);
            System.out.println(index);
            exch(a, hi, index);
            int small = lo - 1;
            for(index = lo; index < hi; ++index){
                if(a[index] < a[hi] ){
                    ++small;
                    if(index != small){
                        exch(a, small, index);
                    }
                }
            }
            small++;
            exch(a, small, hi);
            return small;
        }
    
        private int randRange(Random rand, int min, int max) {
            if(max - min == 0) return min;
            int r = rand.nextInt(max - min) + min;
            return r;
        }
    
        private void exch(int[] nums, int i, int j){
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
    
    

    最大堆优先队列 适用于大量数据

    使用一个容器添加k个数字。容器含有k个数字之后将新的数字与容器中的最大数字比较,如果新数大于最大值则新数不可能为最小的k个数之一,如果新数小于最大值则将容器的最大值提出,加入新数。
    从容器中快速查询最大数可以使用最大优先队列,查询时间复杂度为O(1),基于堆实现的的最大优先队列可以在O(logk)实现删除与插入操作。

    class Solution {
    
        public int[] getLeastNumbers(int[] arr, int k) {
            if(arr == null || arr.length == 0 || arr.length < k || k <= 0) 
                return new int[]{};
            PriorityQueue<Integer> maxPQ = new PriorityQueue<>(new Comparator<Integer>(){
                public int compare(Integer o1, Integer o2) {
                    return o2-o1;
                }
            });
            for(Integer each : arr){
                if(maxPQ.size() < k){
                    maxPQ.add(each);
                }else if(each < maxPQ.peek()){
                    maxPQ.poll();
                    maxPQ.offer(each);
                }
            }
            int[] ans = new int[k];
            for(int i = 0; i < k; i++){
                ans[i] = maxPQ.poll();
            }
            return ans;
        }
    }
    
    

    参考

    采用PriorityQueue实现大小顶堆 解决topK问题

  • 相关阅读:
    docker
    iOS开发之抓取花瓣网json数据
    iOS与Android工程项目的简单对比
    Android与iOS的比较
    Jenkins时间和centos时间相差八小时解决方法
    MYSQL中索引里面的基数是什么意思
    使用Java写一个minio的客户端上传下载文件
    Java 使用AOP实现打印日志
    macOS使用brew安装mysql8.x
    MacOS安装homebrew报错:curl: (7) Failed to connect to raw.githubusercontent.com port 443: Connection refused
  • 原文地址:https://www.cnblogs.com/PythonFCG/p/13859951.html
Copyright © 2011-2022 走看看