题目
求一维数组中最小的k个数字
快排算法
复杂度:O(klgn)
import java.util.*;
class Solution{
//选择一个数,将数组分为大小两个部分
public int partition(int data[],int start,int end){
int pivotvalue=data[start];
while(start<end){
while(start<end && data[end]>=pivotvalue)
--end;
// 将比pviot小的元素移动到低端,此时right空,等待低位比pviotvalue大的数补上
data[start]=data[end];
while(start<end && data[start]<=pivotvalue)
++start;
//此时比pviot大的元素移动到了高端,此时left位相当于空,等待高位比pivotalue小的数补上
data[start]=data[end];
}
//当start=end,完成一次快速排序,此时left相当于空,等待pivotvalue补上
data[start] = pivotvalue;
return start;
}
// 若返回的小标是k-1,则结束;否则,调用partition到下标为k-1
public void getTopk(int[] data,int k){
int start = 0,end = data.length-1;
int index=partition(data,start,end);
while(index!=k-1){
if(index>k-1){
// 从index前面重新查找
end = index-1;
index = partition(data,start,end);
}else{
start=end-1;
index=partition(data,start,end);
}
}
for(int i=0;i<k;i++)
System.out.println(data[i]+"\t");
}
}
堆排序算法
复杂度:O (nlgK)
算法;
1. 创建小根堆,初始化大小为k,堆顶为堆得最大元素
2. 扫描数组,往最小堆插入数据,如果堆得元素个数达到k,那么新元素需要和堆顶元素比较,如果小于堆顶,插入新元素。
3. 最终得到k个最小元素。
import java.util.*;
class MinHeap{
// 堆存储数组
private int[] data;
// 构建小根堆
public MinHeap(int[] data){
this.data=data;
bulidHeap();
}
// 数组转换为小根堆
private void bulidHeap(){
for(int i=(data.length)/2-1;i>=0;i--)
heapify(i); // 对孩子节点调用heapify
}
//简化写法
private void heapify(int k){
int N=data.length;
while(2*k<=N){
int j=2*k;
if(j<N && less(j,j+1))
j++;
if(!less(k,j))
break;
exch(k,j);
k=j;
}
}
/*
// 好理解的写法
private void heapify(int k){
// 获取左右节点的数组的下标
int l=left(i);
int r =right(i);
// 临时变量
int smallest=i;
//若存在左节点,且左节点的值下于根节点
if(l<data.length && data[l]<data[i])
smalleat=l;
if(r<data.length && data[r]<data[smalleat])
smalleat=r;
// 左右节点都大于根节点直接return
if(i==smallest)
return;
//交换节点
swap(i,smalleat);
// 交替后左右子树有影响,对收影响的子树再次heapify
heapify(smalleat);
}
*/
private boolean less(int i,int j)
{
if(data[i]<data[j])
return true;
else
return false;
}
private void exch(int i, int j)
{
int key=data[i];
data[i]=data[j];
data[j]=key;
}
public int getRoot(){
return data[0];
}
// 替换根节点,并重新heapify
public void setRoot(int root)
{
data[0]=root;
heapify(0);
}
}
public class Solution{
public static void main(String[] args){
// 元数据
int[] data={56,275,12,6,45,478,41,1236,456,12,546,45};
//top5
int[] top5=topk(data,5);
for(int i=0;i<5;i++)
System.out.println(top5[i]);
}
private static int[] topk(int[] data,int k){
//取得k个元素放入一个数组topk中
int[] topk=new int [k];
for(int i=0;i<k;i++)
topk[i]=data[i];
// 转换为小根堆
MinHeap heap =new MinHeap(topk);
for(int i=k;i<data.length;i++){
int root = heap.getRoot();
//根据大于堆中最小的数 ,替换堆中的根节点,再转换为堆
if(data[i]>root)
heap.setRoot(data[i]);
}
return topk;
}
}