青训营X豆包AI工具的使用 | 查找热点问题-哈希表 | 豆包MarsCode AI 刷题

45 阅读3分钟

问题描述

给你一个整数数组 nums 和一个整数 k,请你用一个字符串返回其中出现频率前 k 高的元素。请按升序排列。

你所设计算法的时间复杂度必须优于 O(n log n),其中 n 是数组大小。

输入

  • nums: 一个正整数数组
  • k: 一个整数

返回

返回一个包含 k 个元素的字符串,数字元素之间用逗号分隔。数字元素按升序排列,表示出现频率最高的 k 个元素。

参数限制

  • 1 <= nums[i] <= 10^4
  • 1 <= nums.length <= 10^5
  • k 的取值范围是 [1, 数组中不相同的元素的个数]
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

测试样例

样例1:

输入:nums = [1, 1, 1, 2, 2, 3], k = 2
输出:"1,2"
解释:元素 1 出现了 3 次,元素 2 出现了 2 次,元素 3 出现了 1 次。因此前两个高频元素是 1 和 2。

样例2:

输入:nums = [1], k = 1
输出:"1"

样例3:

输入:nums = [4, 4, 4, 2, 2, 2, 3, 3, 1], k = 2
输出:"2,4"

思路

  1. 统计每个元素的频率:我们可以使用一个 HashMap 来存储每个元素及其出现的次数。
  2. 根据频率排序:我们需要根据元素的频率进行排序。由于题目要求时间复杂度优于 O(n log n),我们可以使用一个大小为 k 的最小堆(优先队列)来维护频率最高的 k 个元素。
  3. 构建结果字符串:最后,我们将频率最高的 k 个元素按升序排列,并构建结果字符串。

这题我用Java来实现。getOrDefault用法 getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。

getOrDefault() 方法的语法为:

hashmap.getOrDefault(Object key, V defaultValue)

注: hashmap 是 HashMap 类的一个对象。

参数说明:

  • key - 键
  • defaultValue - 当指定的key并不存在映射关系中,则返回的该默认值

返回值

返回 key 相映射的的 value,如果给定的 key 在映射关系中找不到,则返回指定的默认值。

Java中的Map操作

  • 建立:Map<Integer, Integer> frequencyMap = new HashMap<>();确定键值对的类型(不能为基本数据类型),使用new关键字创建对象

  • 添加元素:使用getOrDefault方法判断Map中有无该元素,若有则返回该元素的值,若无则为0,再使用put方法设置该键的值

  • 排序:使用优先队列PriorityQueue来找到频率最高的前 k 个元素(排序,从大到小)

  • 取元素:用Map.Entry遍历Map

学习建议
对于初学者,可以通过以下方法巩固对优先队列和哈希表的理解:

  1. 多练习类似的题目:尝试解决更多涉及优先队列和哈希表的问题,如“Top K 频繁元素”、“最长连续序列”等。
  2. 理解并手动推导:手动推导数据结构的操作过程,直观感受其工作原理和性能特点。
  3. 阅读相关文档和教程:深入学习 Java 中 PriorityQueue 和 HashMap 的实现细节和使用方法。

通过这些方法,可以更好地掌握优先队列和哈希表的应用,提升算法设计和实现的能力。

代码实现


public class Main {
    public static String solution(int[] nums, int k) {
        // Step 1: 统计每个元素的频率
        Map<Integer, Integer> frequencyMap = new HashMap<>();
        for (int num : nums) {
            frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1);
        }

        // Step 2: 使用最小堆来维护频率最高的 k 个元素
        PriorityQueue<Integer> minHeap = new PriorityQueue<>(
            (a, b) -> frequencyMap.get(a) - frequencyMap.get(b)
        );
        for (int num : frequencyMap.keySet()) {
            minHeap.offer(num);
            if (minHeap.size() > k) {
                minHeap.poll(); // 保持堆的大小为 k
            }
        }

        // Step 3: 构建结果字符串
        List<Integer> resultList = new ArrayList<>(minHeap);
        Collections.sort(resultList); // 按升序排列
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < resultList.size(); i++) {
            if (i > 0) {
                result.append(",");
            }
            result.append(resultList.get(i));
        }

        return result.toString();
    }

    public static void main(String[] args) {
        int[] nums1 = {1, 1, 1, 2, 2, 3};
        int[] nums2 = {1};

        System.out.println(solution(nums1, 2).equals("1,2"));
        System.out.println(solution(nums2, 1).equals("1"));
    }
}
``