您的位置:首页 > Web前端

剑指offer——最小的K个数(堆排或partition,复习排序算法思想精髓)

2017-06-21 16:23 239 查看
题目描述

输入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)

<
4000
span class="hljs-keyword">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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: