算法 - 剑指Offer 最小的k个数

题目

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

解题思路

这题首先最简单的解法是直接对int[]排序, 然后取前K个组成的int[]即可, 但是这里有更好的解法, 使用快速排序,快速排序简单介绍下, 选一个哨兵, 然后将所有比他小的放哨兵左边所有比他大的放右边,这里需要注意的是快拍必须从右边开始,因为我们这里一般选取的哨兵为数组的第一个数字, 理由在代码注释里,然后哨兵的位置可以看成K,如果刚好选的哨兵在K这个地方, 那么后面的排序其实就不需要了, 如果K大于哨兵的位置,说明哨兵的位置到K还没有排序,需要再将将右子串排序下, 如果K小于哨兵的位置,说明K到哨兵的位置还没排序, 需要将左子串在继续排序下, 代码如下。

Java代码实现

import java.util.Arrays;

public class GetLeastNumbers {
    public int[] getLeastNumbers(int[] arr, int k) {
        if(k >= arr.length){
            return arr;
        }
        quickSort(arr, k, 0, arr.length - 1);
        return Arrays.copyOf(arr, k);
    }
    public void quickSort(int[] arrays, int k, int leftIndex, int rightIndex){
        if(leftIndex > rightIndex ){
            return;
        }
        int pivot = arrays[leftIndex];
        int l = leftIndex;
        int r = rightIndex;
        while(l < r){
            //是因为基准数定为最左端的6,如果i先出发寻找大于6的数,会先经过1,2等小于6的数;这就会导致最后 i 和 j 相遇时 j 可能并没有找到小于基准数的数,
            // 再将i,j同时指向的值与基准数交换,就将大于基准数的值交换到了基准数左边
            //举个例子,对于一组数3, 1, 2, 5, 4,如果设3为基准数,先移动 i,则i会在5 处停下,j也在 5 处停下,将5与基准数3交换,
            // 得到5, 1, 2, 3, 4,基准数左边有比基准数大的数5
            while(arrays[r] >= pivot && l < r){
                r --;
            }
            while(arrays[l] <= pivot && l < r){
                l ++;
            }
            if(arrays[l] > pivot || arrays[r] < pivot){
                swap(arrays, r , l);
            }
        }
        swap(arrays, l, leftIndex);
        if(l > k) {
            quickSort(arrays, k, leftIndex, l - 1);
        }
        if(l < k){
            quickSort(arrays, k,l + 1 , rightIndex);
        }
    }
    private void swap(int[] res, int i, int j) {
        int tmp = res[j];
        res[j] = res[i];
        res[i] = tmp;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值