堆的相关习题 面试题17.14最小的K个数 347前K个高频元素 373查找和最小的K对数字
Posted 王嘻嘻-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆的相关习题 面试题17.14最小的K个数 347前K个高频元素 373查找和最小的K对数字相关的知识,希望对你有一定的参考价值。
目录
373、查找和最小的K对数字 - 力扣
面试题17.14、最小的K个数 - 力扣
思路:首先根据题目条件取最小的数构造最大堆,遍历原数组,若当前元素个数大于K,判断K和堆顶元素的关系,若当前元素大于堆顶元素,则大于堆中所有元素,当前元素不入堆;若当前元素小于K ,将堆顶元素出堆,当前元素入堆。最后将堆中保存的元素出堆保存在数组中。
//最小的K个数,取小用大
class Num17_14_SmallestK
public int[] smallestK(int[] arr,int k)
//边界条件
if (arr.length == 0 || k == 0)
return new int[0];
//构造一个最大堆。JDK默认的是最小堆,使用比较器改造为最大堆
Queue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>()
@Override
public int compare(Integer o1, Integer o2)
return o2 - o1;
);
//扫描原数组,优先级队列中只存储K个数
for(int i : arr)
if (queue.size() < k)
queue.offer(i);
else
//当前元素超过了k值,判断扫描元素和堆顶的关系
//若扫描元素 > 堆顶元素,则 > 堆中所有元素,扫描元素不入堆
int peek = queue.peek();//堆顶元素
if (i > peek)
continue;
else
//此时扫描元素 < 堆顶元素,将堆顶元素出队,再将此元素入堆
queue.poll();
queue.offer(i);
//此时最大堆中就保存了最小的k个数,将堆中元素出堆保存在数组中
int[] ret = new int[k];
for (int i = 0; i < k; i++)
ret[i] = queue.poll();
return ret;
347、前K个高频元素 - 力扣
思路:将数组中出现的元素以及出现的次数存储到Map中,扫描Map集合,将前K个频次最高的元素放入最小堆中,当整个集合扫描完毕,最小堆中就存储了前K个频次最高的元素。将最小堆依次出队即可得到答案。
class Solution
//每个不重复元素以及出现的次数
private class Freq implements Comparable<Freq>
private int key;
private int times;
//构造方法
public Freq(int key, int times)
this.key = key;
this.times = times;
//最小堆,元素出现的次数越多就越大
@Override
public int compareTo(Freq o)
return this.times - o.times;
public int[] topKFrequent(int[] nums, int k)
int[] ret = new int[k];
//1.先扫描原nums数组,将每个不重复元素以及出现的次数存储到Map中
Map<Integer,Integer> map = new HashMap<>();
for (int i : nums)
// map.put(i,map.getOrDefault(i,0) + 1);
if (map.containsKey(i))
//此时i已经在map中存在了
map.put(i,map.get(i) + 1);
else
//此时是第一次出现
map.put(i,1);
//2.扫描Map集合,将前K个出现频次最高的元素放入优先级队列中
Queue<Freq> queue = new PriorityQueue<>();
for (Map.Entry<Integer,Integer> entry : map.entrySet())
if (queue.size() < k)
queue.offer(new Freq(entry.getKey(), entry.getValue()));
else
//判断当前对顶元素和当前元素的出现次数关系
Freq freq = queue.peek();
if (entry.getValue() < freq.times)
continue;
else
queue.poll();
queue.offer(new Freq(entry.getKey(), entry.getValue()));
//此时优先级队列中就存储了出现频次最高的前K个pair对象
for (int i = 0; i < k; i++)
ret[i] = queue.poll().key;
return ret;
373、查找和最小的K对数字 - 力扣
思路:首先确定是构造一个最大堆,用自定义类构造比较器成最大堆。扫描两个数组,若数组长度大于K,u或v的遍历到数组完为止;若数组长度小于K,遍历数组nums到K为止。
class Solution
private class Pair
int u;
int v;
public Pair(int u, int v)
this.u = u;
this.v = v;
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k)
// 1.扫描这两个数组,u来自第一个数组,v来自第二个数组,
// 最大堆<Pair>,此时元素的大小关系为pair对象中u + v的值越大认为元素越大
Queue<Pair> queue = new PriorityQueue<>(new Comparator<Pair>()
@Override
public int compare(Pair o1, Pair o2)
return (o2.u + o2.v) - (o1.u + o1.v);
);
// 2.遍历两个数组,u来自第一个数组,v来自第二个数组
for (int i = 0; i < Math.min(nums1.length, k); i++)
for (int j = 0; j < Math.min(nums2.length, k); j++)
if (queue.size() < k)
queue.offer(new Pair(nums1[i], nums2[j]));
else
int add = nums1[i] + nums2[j];
Pair pair = queue.peek();
if (add > (pair.u + pair.v))
continue;
else
queue.poll();
queue.offer(new Pair(nums1[i], nums2[j]));
//此时优先级队列中就存储了和最小的前K个pair对象
List<List<Integer>> ret = new ArrayList<>();
for (int i = 0; i < k && (!queue.isEmpty()); i++)
List<Integer> temp = new ArrayList<>();
Pair pair = queue.poll();
temp.add(pair.u);
temp.add(pair.v);
ret.add(temp);
return ret;
本小节完^_^
以上是关于堆的相关习题 面试题17.14最小的K个数 347前K个高频元素 373查找和最小的K对数字的主要内容,如果未能解决你的问题,请参考以下文章