29.最小的K个数(涉及堆排序)
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
1.堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了
堆排序的基本思路:
a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
//一般升序采用大顶堆,降序采用小顶堆)
//这里构造大顶堆:大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> minnums=new ArrayList<>();
if(input==null||k<=0||k>input.length){
return minnums;
}
//(1) 遍历输入数组,将前k个数插入到推中;
int[] nums=new int[k];//用于放最小的k个数
for(int i=0;i<k;i++){
nums[i]=input[i];//先放前k个数
}
for(int i=k/2-1;i>=0;i--){
adjustHeap(nums,i,k-1);//将数组造成最大堆形式
}
// 继续从输入数组中读入元素做为待插入整数,并将它与堆中最大值比较:
//如果待插入的值比当前已有的最大//值小,则用这个数替换当前已有的最大值;
//如果待插入的值比当前已有的最大值还大,则抛弃这个数,继续读下一个数。
for(int i=k;i<input.length;i++){
if(input[i]<nums[0]){
nums[0]=input[i];
adjustHeap(nums,0,k-1);//重新调整最大堆
}
}
for(int n:nums){
minnums.add(n);
}
return minnums;
}
private void adjustHeap(int[] arr,int start,int length){
int temp=arr[start];
int child=start*2+1;
while(child<=length){
if(child+1<=length&&arr[child+1]>arr[child]){//如果右子结点大于左子结点,则指向右子结点
child++;
}
if(arr[child]<temp){
break;
}
//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
arr[start]=arr[child];
start=child;
child=child*2+1;
}
arr[start]=temp;//将temp值放到最终的位置
}
基于堆排序算法,构建最大堆。时间复杂度为O(nlogk)
(1) 遍历输入数组,将前k个数插入到推中;(利用multiset来做为堆的实现)
(2) 继续从输入数组中读入元素做为待插入整数,并将它与堆中最大值比较:如果待插入的值比当前已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还大,则抛弃这个数,继续读下一个数。
这样动态维护堆中这k个数,以保证它只储存输入数组中的前k个最小的数,最后输出堆即可。
2.如果用快速排序,时间复杂度为O(nlogn);
3.如果用冒泡排序,时间复杂度为O(n*k)
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> alist=new ArrayList<Integer>();
if(k>input.length) {
return alist;
}
for(int i=0;i<k;i++){
for(int j=0;j<input.length-i-1;j++){
if(input[j]<input[j+1]){
int temp=input[j];
input[j]=input[j+1];
input[j+1]=temp;
}
}
alist.add(input[input.length-i-1]);
}
return alist;
}
}