算法练习-排序 LeetCode 剑指 Offer 40. 最小的k个数

今日心情:感觉做过的题还是不会 😮‍💨😮‍💨

题目描述:

 LeetCode 剑指 Offer 40. 最小的k个数

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


解题代码:

class Solution {

    public int[] getLeastNumbers(int[] arr, int k) {
        process(arr,0,arr.length-1);

        int[] res = new int[k];

        for(int i = 0; i < k ; i++){
            res[i] = arr[i];
        }
        return res;
    }

    public void process(int[] arr, int L, int R){
        if(L >= R){return;}
        int[] equalRange = partition(arr,L,R);
        process(arr,L,equalRange[0]-1);
        process(arr,equalRange[1]+1,R);
    }

    public int[] partition(int[] arr, int L, int R){
        int index = L;
        int lessR = L-1;
        int moreR = R;

        while(index < moreR){
            if(arr[index] < arr[R]){
                swap(arr,++lessR,index++);
            }else if(arr[index] > arr[R]){
                swap(arr,--moreR,index);
            }else{
                index++;
            }
        }
        swap(arr,moreR,R);

        return new int[]{lessR+1,moreR};
    }

    public void swap(int[] arr, int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }


}

解题思路:

采用快排对整个数组进行升序排序

(1)将整个数组按照最后一个数据进行大小划分,大的放在右边,小的放在左边。

        -- 设置范围L 左边起始位置, R右边终点位置,lessR = L-1 小于最后一个数的指标,moreR =R 大于最后一个数的指标。

        -- 从 index = L 开始,以数组最后一个数为判断标准,如果当前index所指的数小于最后一个数,将,lessR加一,与index位置的数进行互换,实际上该数位置不变,然后index加1. 如果当前index所指的数大于最后一个数,此时moreR减1,index不变,对两个位置上的数进行交换。如果相等则index加1,移动index继续判断下一个数。

       -- 当 index == moreR 的时候,说明所有交换完成,退出循环。注意此时最后一个数需要和moreR换位置。

       --  返回 lessR+1 和 moreR 值,进行下一次递归的范围判断。

    public int[] partition(int[] arr, int L, int R){
        int index = L;
        int lessR = L-1;
        int moreR = R;

        while(index < moreR){
            if(arr[index] < arr[R]){
                swap(arr,++lessR,index++);
            }else if(arr[index] > arr[R]){
                swap(arr,--moreR,index);
            }else{
                index++;
            }
        }
        swap(arr,moreR,R);
        return new int[]{lessR+1,moreR};
    }

        交换函数 

    public void swap(int[] arr, int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

(2)递归函数:(对不等于最后一个数的左右两段进行排序,递归实现整个数组的升序排序)

        -- 退出递归条件:L与R边界撞上的时候

        -- 获取左右边界范围(equalRange[0] 是 lessR+1 ,即等于最后一个数的第一个下标范围,equalRange[1] 是moreR , 即等于最后一个数的最后一个下标范围

        -- 对于不等于最后一个数的左右范围进行递归

            递归的左边范围: L 到 equalRange[0]-1        

            递归的右边范围 :equalRange[1]+1 到 R

    public void process(int[] arr, int L, int R){
        if(L >= R){return;}
        int[] equalRange = partition(arr,L,R);
        process(arr,L,equalRange[0]-1);
        process(arr,equalRange[1]+1,R);
    }

(3)调用递归函数对数组进行升序排序,然后输出前k个数,即为当前数组中前k个最小的值


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值