面试手撕代码常见TopK问题(Java小顶堆实现)

public class TopK{
        public static void main(String[] args){
		 int[] data={3,5,8,7,9,2,4,3,1,6};
		//举例,如获取top5
		int[] top5=topK(data,5);
		//1.先从原始数据中取出topK的前k个数据建立小顶堆
		for(int i=0;i<5;i++){
		  System.out.println(top5[i]);
		  }
		}//main结束
		//2.建堆,剩下的N-K个数据来一个排序一个
		//3.从data数组中获取最大的k个数
	    public static int[] topK(int[] data,int k){
		  int[] topk=new int[k];
		  for(inti=0;i<k;i++0){
		   top[i]=data[i];
		   }
		  //转换成小顶堆
		  MinHeap heap=new MinHeap(topk);
		  //从k开始,即剩下的数,进行遍历并加入到小顶堆
		  forint i=k;i<data;i++){
		    int root=heap.getRoot();
		//当当前数据大于堆中根节点,即最小的数,说明在范围之内,先保留
			if(data[i]>root){
			  heap.setRoot(data[i]);
			  }
		}//for循环结束
		return topk;
	}//topk方法结束
} //TopK类结束

//构建小顶堆的类
public  class MinHeap{
   //堆的存储结构,数组保存
   private int[] data;
   
   //将数组数据建立小顶堆
   public MinHeap(int[] data){
      this.data=data;
	  buildHeap();
	  }
	  
	 //具体建立最小堆
   private void bulidHeap(){
	 for(int i=(data.length)/2-1;i>=0;i--){
	   heapfy(i);
	   }
	 }
	 
	 //调整堆
	 private void heapify(int i){
	     int l=left(i);
	     int r=right(i);
	     int smallest=i; 
	 //存在左节点且左节点小于根节点的值
	   if(l<data.length&&data[l]<data[i])
	       smallest=l;
		//存在右节点且右节点小于以上节点的较小值
	 if(r<data.length&&data[r]<data[smallest])
	    smallest=l;
	   if(i==smallest)
	   return;
	   
	   //交换根节点和左右节点中最小的那个值,把根节点的值替换
	   swap(i,smallest);
	   //由于替换影响,需要对子树进行再次排序,直到;
	   heapify(smallest); 
	 }
	 
	  //获取右节点的数组下标
	 private  int right(int i){
	    return (i+1)<<1;
		}
		//获取左节点的数组下标
	 private int left(int i){
        return ((i+1)<<1)-1;
        }		
	 //交换元素位置
	 private void swap(int i,int j){
	   int temp=data[i];
	   data[i]=data[j];
	   data[j]=temp;
	   }  
	 //获取堆中的最小元素,根元素
	 public int getRoot(){
	    return data[0];
		}
	//替换根元素,并重新heapify
	  public void setRoot(int root){
	  data[0]=root;
	    heapify(0);
		}
	}
}   
	   
	   
	   
发布了279 篇原创文章 · 获赞 23 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_30242987/article/details/104800716