TOP-K问题

其实这个>其实我是一个算法渣,也不怎么会算法,只是最近遇到这个问题,就顺手谷歌一下,遇到一个不错的解法,记录一下

修改部分代码就可以获取最大堆 和 最小堆,参考了这篇文章基于堆实现的优先级队列:PriorityQueue 解决 Top K 问题



import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Random;

/**
 * 指定元素数量的最大堆
 * @author Think
 *
 * @param <E>
 */
public class FixSizedPriorityQueue <E extends Comparable<E>> implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private PriorityQueue<E> queue;
	private int maxSize; // 堆的最大容量

	public FixSizedPriorityQueue(int maxSize) {
		if (maxSize <= 0)
			throw new IllegalArgumentException();
		this.maxSize = maxSize;
		this.queue = new PriorityQueue(maxSize, new Comparator<E>() {
			public int compare(E o1, E o2) {
				// 生成最小堆使用o2-o1,生成最大堆使用o1-o2, 并修改 e.compareTo(peek) 比较规则
				return o1.compareTo(o2);
			}
		});
	}

	public void add(E e) {
		
		if (queue.size() < maxSize) { // 未达到最大容量,直接添加
			queue.add(e);
		} else { // 队列已满
			E peek = queue.peek(); //如果o2-o1 大于0 那么队列头元素是最大的,要得到的是最小堆,那么就是留peek和e的较小值
			//同样类似的o1-o2,对头元素是最小的,要生成最大堆,保留peek和e的较大者
			if (peek.compareTo(e) < 0) { // 将新元素与当前堆顶元素比较,保留较大的元素
				queue.poll();
				queue.add(e);
			}
		}
	}
	//队列中是否包含该元素
	public boolean contains(E e){
		return queue.contains(e);
	}
	//队列实际元素个数
	public int getSize() {
		return queue.size();
	}
	
	public List<E> reverse(){
		
		List<E> resultList  = new  ArrayList<E>(maxSize);
		
		while (!this.queue.isEmpty()) {
			resultList.add(queue.poll());
		}
		 Collections.reverse(resultList);
		 return resultList;
	}
	
	
	

	public static void main(String[] args) {
		final FixSizedPriorityQueue<Integer> pq = new FixSizedPriorityQueue(10);
		Random random = new Random();
		int rNum = 0;
		System.out.println("100 个 0~999 之间的随机数:-----------------------------------");
		for (int i = 1; i <= 20; i++) {
			rNum = random.nextInt(1000);
			System.out.println(rNum);
			pq.add(rNum);
		}
		System.out.println("PriorityQueue 本身的遍历是无序的:-----------------------------------");
		Iterable<Integer> iter = new Iterable<Integer>() {
			public Iterator<Integer> iterator() {
				return pq.queue.iterator();
			}
		};
		for (Integer item : iter) {
			System.out.print(item + ", ");
		}
		System.out.println();
		System.out.println("PriorityQueue 排序后的遍历:-----------------------------------");
		
		List<Integer> reverse = pq.reverse();
		System.out.println(reverse);
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值