LeetCode——692 前K个高频单词(JAVA)

给一非空的单词列表,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。

示例 1:

输入: ["i", "love", "leetcode", "i", "love", "coding"], k = 2
输出: ["i", "love"]
解析: "i""love" 为出现次数最多的两个单词,均为2次。
    注意,按字母顺序 "i""love" 之前。

示例 2:

输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
输出: ["the", "is", "sunny", "day"]
解析: "the", "is", "sunny""day" 是出现次数最多的四个单词,
    出现次数依次为 4, 3, 21 次。

思路

这题主要就是个排序的问题,感觉用C/C++混合的方式写起来会很方便,可以用algorithm里的sort函数排序,java里得重写compare函数,而且返回值容易让人弄不清楚。

我这里是这么理解的,假设元素o1在前,o2在后:

  • 如果return 1,就说明o2o1要交换位置,变成o2在前,o1在后;
  • 如果return -1,就说明o1o2保持原位,仍然是o1在前,o2在后;
  • 如果return 0,就说明o1==o2

回到这题,因为是要找前k个频率最高的单词,很明显是要建立一个关于频率的大顶堆,然后取出前k个堆顶元素即可。我这里是写了一个Word类来绑定字符串和出现频率之间的关系,因此,建立的大顶堆里面放的元素也应该是Word类型的。

接下来的步骤就很简单了。主要是compare函数,因为题目要求如果有相同频率,必须按字典序升序,因此,在compare里还应该判断,当频率相同时,直接返回o1.val.compareTo(o2.val)即可,默认即为字典序升序排列。

代码

public class Solution {
	class Word{
		String val;
		int fre;
		Word(String val, int fre){
			this.val = val;
			this.fre = fre;
		}
	}
	public List<String> topKFrequent(String[] words, int k){
		int n = words.length;
		Map<String, Integer> map = new HashMap<String, Integer>();
		for(String x : words) {
			if(map.get(x)==null) {
				map.put(x, 1);
			}
			else {
				int val = map.get(x);
				val++;
				map.put(x, val);
			}
		}
		PriorityQueue<Word> maxHeap = new PriorityQueue<Word>(n, new Comparator<Word>() {
			@Override
			public int compare(Word o1, Word o2) {
				if(o1.fre!=o2.fre) {
					if(o1.fre<o2.fre) return 1;
					else if(o1.fre>o2.fre) return -1;
					else return 0;
				}
				else {
					return o1.val.compareTo(o2.val);
				}
			}
		});
		List<Word> list = new ArrayList<Word>(); 
		for(String x : map.keySet()) {
			Word tempWord = new Word(x, map.get(x));
			list.add(tempWord);
		}
		for(Word x : list) {
			maxHeap.offer(x);
		}
		List<String> result = new ArrayList<String>();
		for(int i=0;i<k;i++) {
			Word maxFre = maxHeap.poll();
			result.add(maxFre.val);
		}
		return result;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值