剑指offer——最小的K个数(堆排或partition,复习排序算法思想精髓)
来源:互联网 发布:金山恢复数据恢复软件 编辑:程序博客网 时间:2024/05/21 12:20
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
思路:
维护一个由k个值组成的动态最大堆。然后接下来的每个数字和堆顶的数据比较,如果比堆顶的数据小,那就把数据放入堆中。最小堆内部不用严格排序,只要保证堆中最大的数字在堆顶即可。
或者直接快排,再把前n位数字输出。
import java.util.*;public class Solution { public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { ArrayList<Integer> list = new ArrayList<>(); if(k<=0||k>input.length) return list; if(k>1){ // 这里先对前k个数进行堆排序,组成了一个最大堆(堆顶为最大值) for(int i = k/2-1; i>=0; i-- ){ heap(input,i,k); } } // 然后将剩下的元素插入最大堆,方法是与堆顶的元素进行比较,如果小于堆顶元素,即插入,并维护堆 for(int i = k; i<input.length; i++){ if(input[i]<input[0]){ input[0] = input[i]; heap(input,0,k); } } for(int i = 0; i<k; i++){ list.add(input[i]); } return list; } public void heap(int[] input, int i, int k){ int flag = i; if(2*i+1<k){ if(input[2*i+1]>input[flag]) flag = 2*i+1; } if(2*i+2<k){ if(input[2*i+2]>input[flag]) flag = 2*i+2; } if(flag!=i){ int temp = input[i]; input[i] = input[flag]; input[flag] = temp; heap(input,flag,k); } }}
另一种解法,基于partition的思想
因为快排每次都能得到基于分界点的数组,分界点左边的元素一定小于分界点上的元素。如果此分界点正好是k,则得到了最小的k个数。
最坏情况是,一直没有得到这个点,得到了一个部分排序的数组。但时间复杂度仍小于O(nlogn)
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { ArrayList<Integer> list = new ArrayList<>(); if (k <= 0 || k > input.length) return list; int start = 0; int end = input.length-1; int index = partition(input,start,end); while(index!=k){ // 把判断写在主函数,很好! if(index>k){ end = index-1; index = partition(input,start,end); } if(index<k){ start = index+1; index = partition(input,start,end); } } for(int i = 0; i<k; i++){ list.add(input[i]); } return list; } public int partition(int[] input, int start, int end){ if(start>=end) return start; int flag = input[end]; while(start<end){ while(input[start]<=flag&&start<end) ++start; int temp = input[start]; input[start] = input[end]; input[end] = temp; while(input[end]>=flag&&end>start) --end; temp = input[start]; input[start] = input[end]; input[end] = temp; } return start; }
阅读全文
0 0
- 剑指offer——最小的K个数(堆排或partition,复习排序算法思想精髓)
- 剑指Offer面试题30最小的K个数(涉及堆或快排)
- 【剑指offer】 堆排序查找最小的K个数
- 最小的K个数:二种思路:快排的精髓-----最大堆
- 剑指offer—最小的K个数
- 剑指offer — 最小的k个数
- 堆排序(最小的K个数)
- 剑指Offer——(29)最小的k个数
- 剑指Offer-30-最小的k个数-最大堆
- 最小的k个数(剑指offer)
- 最小的K个数,堆排序——剑指offor Java程序
- 《剑指offer》——最小的k个数
- 剑指offer——最小的K个数
- 剑指Offer—— 最小的K个数
- 剑指offer——最小的K个数
- 剑指Offer—29—最小的 K 个数
- 剑指offer——29.最小的k个数
- 剑指offer 面试题30—最小的k个数
- Jvav 中Synchronized的使用
- CI持续集成系统环境---部署Jenkins完整记录
- java 笔记
- strlen与sizeof区别
- web1.0与web2.0的区别介绍附举例
- 剑指offer——最小的K个数(堆排或partition,复习排序算法思想精髓)
- [python每日一练]--0005:把图片大小控制在iphone5的分辨率以下
- java读取csv文件并将其转成json
- 真实案件之:意料之外的 RAC 宕机罪犯
- Web Api Self Host大文件上传功能
- Unity 2017 使用UGUI制作大转盘抽奖
- 读取xlsx文件
- 利用Chrome与迅雷下载斗鱼录播视频
- sql 涉及时间