算法:最小的k个数

问题

  • 输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

解决

// 1、利用api一级额外数据结构进行:先遍历排序再输出
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        int len1=arr.length;
        if(len1==0) return new int[0];
        int[] cur=new int[k];
        Arrays.sort(arr);
        for(int i=0;i<k;i++){
            cur[i]=arr[i];
        }
        return cur;
    }
}

//2、使用大根堆解决
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        int[] cur=new int[k];
        if(k==0) return cur;
        PriorityQueue<Integer> queue=new PriorityQueue<Integer>(new Comparator<Integer>(){
                public int compare(Integer num1,Integer num2){
                    return num2-num1;                  //比较器,取大的值
                }
        }); 
        for(int i=0;i<k;i++){                          //将前k个数放到大根堆中
            queue.offer(arr[i]);
        }
        for(int i=k;i<arr.length;i++){                 //在arr剩余数中,如果小于堆的首元素就让他替换堆顶元素,然后堆自动进行排序成大根堆
            if(queue.peek()>arr[i]){
                queue.poll();
                queue.offer(arr[i]);
            }
        }
        for(int i=0;i<k;i++){
            cur[i]=queue.poll();
        }
        return cur;
    }
}


//3、利用快排思想
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        randomizedSelected(arr, 0, arr.length - 1, k);
        int[] vec = new int[k];
        for (int i = 0; i < k; ++i) {
            vec[i] = arr[i];
        }
        return vec;
    }

    private void randomizedSelected(int[] arr, int l, int r, int k) {
        if (l >= r) {
            return;
        }
        int pos = randomizedPartition(arr, l, r);
        int num = pos - l + 1;
        if (k == num) {
            return;
        } else if (k < num) {
            randomizedSelected(arr, l, pos - 1, k);
        } else {
            randomizedSelected(arr, pos + 1, r, k - num);
        }
    }

    // 基于随机的划分
    private int randomizedPartition(int[] nums, int l, int r) {
        int i = new Random().nextInt(r - l + 1) + l;
        swap(nums, r, i);
        return partition(nums, l, r);
    }

    private int partition(int[] nums, int l, int r) {
        int pivot = nums[r];
        int i = l - 1;
        for (int j = l; j <= r - 1; ++j) {
            if (nums[j] <= pivot) {
                i = i + 1;
                swap(nums, i, j);
            }
        }
        swap(nums, i + 1, r);
        return i + 1;
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

posted @   new_monkey  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示