LeetCode[面试题17.14]最小的K个数

难度:中等

题目:

设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。 


 示例:

输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]

提示:

  • 0 <= len(arr) <= 100000
  • 0 <= k <= min(100000, len(arr))

 Related Topics

  • 数组
  • 分治
  • 快速选择
  • 排序
  • 堆(优先队列)

重点!!!解题思路

第一步:

明确解题手段:此题比较简单的做法就是使用堆来解决,但是此章节我们练习的是排序算法,即此题我们采用排序算法来解决

第二步:

还是像排序算法 中使用模仿STL的快速排序思想,这里面我们就不需要使用插入排序了,直接使用手写的根据基准值快排即可(分区思想)

第三步:

分区之后,我们判断分区的大小和K的大小,不够或者超出就重新进行递归求解,正好相等那就返回结果 

源码+讲解:

    class Solution {
        public int[] smallestK(int[] arr, int k) {
            int[] ans=new int[k];  //创建一个结果集
            if (k==0) return ans;
            quick_sort(arr,0,arr.length-1,k);  //k不为0就进行递归求解
            for (int i=0;i<k;i++){  //将原数组的拷贝到结果集中
                ans[i]=arr[i];
            }
            return ans;
        }
        public int getmid(int a,int b,int c){  //取基准值
            int max=Math.max(a,Math.max(b,c));
            int min=Math.min(a,Math.max(b,c));
            if (a!=max && a!=min) return a;
            if (b!=max && b!=min) return b;
            return c;
        }
        public void swap(int[] arr,int i,int j){  交换数组值
            int t=arr[i];
            arr[i]=arr[j];
            arr[j]=t;
        }
        public void quick_sort(int[] arr,int l,int r,int k){
            if (l>=r) return;  //边界范围
            int i=l,j=r,m=getmid(arr[i],arr[j],arr[(i+j)/2]);  //拷贝边界+取基准值
            do {
                while (arr[i]<m) i++;
                while (arr[j]>m) j--;
                if (i<=j){  //此时arr[i]>arr[j] 要进行交换
                    swap(arr,i,j);
                    i++;  //交换后都进行移动
                    j--;
                }
            }while (i<=j);  //边界范围
            if (j-l==k-1) return;  //j是已排序好的右边界 j-l为已排序号的数组大小
            if (j-l>=k){
                quick_sort(arr,l,j,k);  //超出即再从已知范围继续寻找k个数
            }else {
                quick_sort(arr,i,r,k-i+l);  //少了就从i开始到数组结尾找k-(j-l)-1个数,化简j+1=r 即最后化简为k-i+1
            }
        }
    }

运行结果:

 系列持续更新中,喜欢练习算法的那就点个攒吧  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月亮被咬碎成星星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值