leetcode【栈与队列—中等】 347.前 K 个高频元素

简介: leetcode【栈与队列—中等】 347.前 K 个高频元素

题目


题目来源leetcode


leetcode地址:347. 前 K 个高频元素,难度:中等。


题目描述(摘自leetcode):


给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
提示:
1 <= nums.length <= 105
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的


本地调试代码:


class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        ...
    }
    public static void main(String[] args) {
        int[] nums = new int[]{1,1,1,2,2,3};
        System.out.println(Arrays.toString(new Solution().topKFrequent(nums,2)));
    }
}



题解


NO1:哈希表+优先队列


思路: 先使用哈希表来进行统计对应值的频率,之后创建一个优先队列设置一个从小到大排序的比较器,每次插入一组key、value后,判断当前的容量是否>k个,若是大于了直接将队头的出队(在队列里频率最小的),最终遍历取出队列中的k组数据即可。


代码:


public int[] topKFrequent(int[] nums, int k) {
    //使用map来进行统计指定指定数的频率,key为num,value为频率
    Map<Integer,Integer> map = new HashMap<>();
    for (int num : nums) {
        map.put(num,map.getOrDefault(num,0)+1);
    }
    Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
    //创建优先队列,传入Comparator匿名接口类,插入队列的元素从小到达排列
    PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1,o2)->o1.getValue()-o2.getValue());
    for (Map.Entry<Integer, Integer> entry : entries) {
        queue.offer(entry);
        if(queue.size() > k){  //一旦队列中的数量大于k,直接将频率最小的出队(队头)
            queue.poll();
        }
    }
    //最终取出对应的最大k值
    int[] maxNums = new int[k];
    for (int i = k-1; i >=0 ; i--) {
        maxNums[i] = queue.poll().getKey();
    }
    return maxNums;
}


NO2:排序遍历+优先队列

思路:首先进行从小到大排序,之后对整个数组进行遍历,以[i]!=[i-1]来作为存储到队列的依据,队列按照从大到小排序,每次入队后判断是否>k个,若是大于出队。最终遍历k个即可获取到前k个高频元素。


代码:


public int[] topKFrequent(int[] nums, int k) {
    Arrays.sort(nums);
    //优先队列,按照频率从小到大排列(Comparator返回值为负数就从小到大排列,若是正数从大到小)
    PriorityQueue<int[]> queue = new PriorityQueue<int[]>((o1, o2) -> o1[1] - o2[1]);
    //对数组进行遍历操作
    int i = 1;
    int j = 1;
    for (; i < nums.length; i++) {
        if (nums[i] == nums[i - 1]) {
            j++;
        } else {
            queue.offer(new int[]{nums[i - 1], j});
            if (queue.size() > k) {  //一旦大于原本k个数量就进行移除
                queue.poll();
            }
            j = 1;
        }
    }
    queue.offer(new int[]{nums[i - 1], j});
    if (queue.size() > k) {
        queue.poll();
    }
    //从队列中取出k个
    int[] maxNums = new int[k];
    for (int l = 0; l < k; l++) {
        maxNums[l] = queue.poll()[0];
    }
    return maxNums;
}


相关文章
|
1月前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
1月前
|
算法 索引
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
这篇文章介绍了LeetCode第34题"在排序数组中查找元素的第一个和最后一个位置"的解题方法,通过使用双指针法从数组两端向中间同时查找目标值,有效地找到了目标值的首次和最后一次出现的索引位置。
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 30. 包含min函数的栈
本文提供了实现一个包含min函数的栈的Python代码,确保min、push和pop操作的时间复杂度为O(1)。
18 4
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 09. 用两个栈实现队列
使用两个栈实现队列的Python解决方案,包括初始化两个栈、实现在队列尾部添加整数的appendTail方法和在队列头部删除整数的deleteHead方法,以及相应的示例操作。
33 2
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer II 082. 含有重复元素集合的组合
解决LeetCode平台《剑指 Offer II 082. 含有重复元素集合的组合》题目的Python代码实现,通过深度优先搜索算法找出所有和为特定目标值的数字组合,并在搜索过程中通过排序和跳过重复元素来避免解集中出现重复组合。
37 2
|
1月前
|
算法
LeetCode第27题移除元素
这篇文章介绍了LeetCode第27题"移除元素"的解题方法,通过使用双指针技巧,有效移除数组中特定值的元素并返回新数组的长度。
|
1月前
|
算法 索引 Python
【Leetcode刷题Python】34. 在排序数组中查找元素的第一个和最后一个位置(二分查找)
解决LeetCode "在排序数组中查找元素的第一个和最后一个位置" 问题的方法。第一种方法是使用两次二分查找,首先找到目标值的最左边界,然后找到最右边界。第二种方法是利用Python的list.index()方法,先正序找到起始位置,再逆序找到结束位置,并给出了两种方法的Python实现代码。
46 0
|
1月前
|
Python
【Leetcode刷题Python】203.移除链表元素
文章提供了三种删除链表中特定值节点的方法:迭代法、虚拟节点迭代删除法和递归法,并给出了相应的Python实现代码。
15 0
|
1月前
|
Python
【Leetcode刷题Python】641.循环双端队列
文章介绍了如何实现一个循环双端队列,包括其操作如插入、删除、获取队首和队尾元素,以及检查队列是否为空或已满,并提供了Python语言的实现代码。
18 0
|
1月前
|
Python
【Leetcode刷题Python】232. 用栈实现队列
如何使用Python语言通过两个栈来实现队列的所有基本操作,包括入队(push)、出队(pop)、查看队首元素(peek)和判断队列是否为空(empty),并提供了相应的代码实现。
15 0