leecode 347. 前 K 个高频元素

本文介绍如何使用小顶堆数据结构解决前K个高频元素的问题,通过Java实现,详细解析了从哈希映射到优先队列转换的过程,包括插入和维护操作。

​​​​​​347. 前 K 个高频元素

 

        本题还是细节处理比较多,我不太熟悉小顶堆大顶堆,这个题花了一个多小时在搞基础,具体细节在代码部分。

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i ++) {
            //getOrDefault():如果map中没有nums[i],则返回值0
            map.put(nums[i], map.getOrDefault(nums[i],0) + 1);
        }
        // int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
        //(e1, e2) -> e2.getValue() - e1.getValue()
        //这一步是制造小顶堆,m是先入的值,n是后入的值
        //如果n<m,return false,则需要交换n和m位置,m放堆顶,则为小顶堆,反之为大顶堆。
        //优先队列用比较器改变小顶堆大顶堆。
        //优先队列中存放的是数组int[],数组中0位置是map的key,1位置是map的value。
        PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>(){
            public int compare(int[] m, int[] n) {
                return m[1] - n[1];
            }
        });
        //entrys是java中Map键值对的一对映射,entrySet是Map的键值对集合
        for (Map.Entry<Integer,Integer> entry : map.entrySet()) {
            int num = entry.getKey(),count = entry.getValue();
            if (queue.size() == k) {
                //小顶堆,所以当前队头储存的是当前放入元素中出现次数最少的。
                //如果当前队头存放的数组的第二个位置(即当前存放的最低次数的数字)的值小于当前准备放入的值,则将队头元素移出,放入新数组。
                //queue.peek()[1]相当于int[1]
                if (queue.peek()[1] < count) {
                    queue.poll();
                    queue.offer(new int[]{num, count});
                }
            } else {
                queue.offer(new int[]{num, count});
            }
        }
        int[] ret = new int[k];
        //这一步是把int[0]的值拿出来放入ret数组,这就是最终结果,int[0]就是出现前k高的元素
        for (int i = 0; i < k; ++i) {
            ret[i] = queue.poll()[0];
        }
        return ret;
    }
}

<think>好的,我现在需要帮用户准备LeetCode面试常见题型及解法。首先,用户已经提供了一些参考资料,包括引用[1]、[2]、[3],涉及计数问题、滑动窗口、哈希表等。我需要根据这些信息,结合常见的LeetCode题型,整理出一个结构清晰的回答。 首先,常见的LeetCode题型有哪些呢?通常包括数组和字符串、链表、树与图、动态规划、回溯算法、滑动窗口、哈希表、堆和、数学问题等。用户提到的引用中提到了计数类型、滑动窗口、哈希表,这些都需要重点覆盖。 接下来,我需要按照用户的要求,分点列出题型及解法,每个部分给出示例题号和解题思路。同时,要引用用户提供的参考资料中的例子,比如引用[1]中的387题,引用[2]中的3题,引用[3]中的快乐数问题。 然后,生成相关问题,可能需要根据每个题型提出相关问题,比如数组中的双指针应用,或者动态规划的优化方法。但根据用户示例中的相关问题,可能更偏向于针对每个题型的进一步提问,比如如何优化、应用场景等。 需要注意的是,用户要求回答结构清晰,逐步解决问题,保证真实可靠。所以每个题型需要简明扼要地说明解题思路,并附上例题和可能的代码示例,但代码示例需要符合用户给的格式,比如Python。 另外,用户提供的引用中有提到滑动窗口的时间复杂度优化到O(n),哈希表用于检测循环,这些都要在相应的部分提到,并正确标注引用。例如,在滑动窗口部分提到例题3,引用[2],在哈希表部分提到快乐数问题,引用[3]。 还需要确保数学表达式使用正确的格式,比如变量用$...$包裹,独立公式用$$...$$。不过当内容可能数学公式不多,但如果有的话需要正确应用。 最后,生成相关问题部分,需要针对每个题型提出相关问题,可能包括解法优化、时间复杂度分析、应用场景等。例如,数组和字符串部分可能问如何优化空间复杂度,滑动窗口如何扩展到其他问题等。 现在,整理结构: 1. 数组与字符串:双指针、哈希表计数(例题387引用[1]) 2. 滑动窗口:无重复字符的最长子串(例题3引用[2]) 3. 哈希表应用:快乐数(引用[3]) 4. 链表:虚拟头节点、快慢指针 5. 树与二叉树:递归、DFS/BFS 6. 动态规划:状态转移方程 7. 回溯算法:排列组合问题 8. 堆与优先队列:Top K问题 每个部分给出解题思路、例题和代码示例(如有必要),并正确标注引用。然后生成相关问题,例如数组相关的优化方法,滑动窗口的复杂度分析等。 需要检查是否有遗漏的常见题型,比如、队列、位运算等,但考虑到用户提供的引用,可能重点放在提到的部分。不过为了全面性,还是应该覆盖更多常见题型。 现在开始组织内容,确保每个部分简洁,包含例题和引用,最后生成相关问题。</think>### LeetCode 面试常见题型及解法 #### 1. 数组与字符串 **核心方法**:双指针、哈希表计数、原地修改 - **双指针**:用于有序数组去重、两数之和等问题。例如用左右指针夹逼法在$O(n)$时间内找到两数之和。 - **哈希表计数**:统计元素频率,如$387$. 字符串中的第一个唯一字符[^1]。 ```python def firstUniqChar(s: str) -> int: freq = {} for c in s: freq[c] = freq.get(c, 0) + 1 for i, c in enumerate(s): if freq[c] == 1: return i return -1 ``` #### 2. 滑动窗口 **优势**:将暴力遍历优化到$O(n)$时间复杂度[^2]。 - **关键点**:窗口左右指针移动条件,如$3$. 无重复字符的最长子串。 ```python def lengthOfLongestSubstring(s: str) -> int: char_set = set() left = max_len = 0 for right in range(len(s)): while s[right] in char_set: char_set.remove(s[left]) left += 1 char_set.add(s[right]) max_len = max(max_len, right - left + 1) return max_len ``` #### 3. 哈希表与数学 **应用场景**:检测循环、快速查找。 - **快乐数问题**:通过哈希表记录平方和避免无限循环[^3]。 $$n = 19 \rightarrow 1^2 + 9^2 = 82 \rightarrow 8^2 + 2^2 = 68 \rightarrow \dots$$ #### 4. 链表 **核心技巧**:虚拟头节点、快慢指针。 - **虚拟头节点**:简化头节点删除操作。 - **快慢指针**:找中点或检测环,如$141$. 环形链表。 #### 5. 树与二叉树 **高频考点**:递归遍历、DFS/BFS。 - **递归三要素**:终止条件、本级任务、返回值。例如$104$. 二叉树的最大深度。 ```python def maxDepth(root: TreeNode) -> int: if not root: return 0 return 1 + max(maxDepth(root.left), maxDepth(root.right)) ``` #### 6. 动态规划 **核心思想**:定义状态转移方程,避免重复计算。 - **经典问题**:$70$. 爬楼梯($dp[n] = dp[n-1] + dp[n-2]$),背包问题。 #### 7. 回溯算法 **适用场景**:排列、组合、子集问题。 - **模板**:选择→递归→撤销选择,如$46$. 全排列。 #### 8. 堆与优先队列 **典型应用**:Top K 问题、合并K个有序链表。 - **Python实现**:使用`heapq`模块,如$215$. 数组中的第K个最大元素。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值