堆的相关习题 ​​​​​​​面试题17.14最小的K个数 ​​​​​​​347前K个高频元素 373查找和最小的K对数字

Posted 王嘻嘻-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆的相关习题 ​​​​​​​面试题17.14最小的K个数 ​​​​​​​347前K个高频元素 373查找和最小的K对数字相关的知识,希望对你有一定的参考价值。

目录

面试题17.14、最小的K个数 - 力扣 ​​​​​​​

347、前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对数字的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode刷题面试题17.14-简单-最小k个数

LeetCode 面试题 17.14 最小K个数[排序 最小堆 快排] HERODING的LeetCode之路

java面试题2

大厂面试题C语言的数据存储相关习题

大厂面试题C语言的数据存储相关习题

面试题9:数组堆化堆的插入堆的删除堆排序