查找热点数据问题 (难)| 豆包MarsCode AI刷题

149 阅读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 个高频元素的集合是唯一的 给定一个nums数组:int nums[ ],一个整数:k,输出一串字符串。

速成3天python但是算法仍写不习惯,故我写了第一个cpp算法后转译为python,pass~

代码思路(c++):

#include <iostream>
#include <queue>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;

// 定义一个结构体来存储整数和它的频率
struct NumFreq {
    int num;
    int freq;
    NumFreq(int n, int f) : num(n), freq(f) {}
};

// 定义比较器,用于优先队列
struct Compare {
    bool operator()(const NumFreq& a, const NumFreq& b) const {
        if (a.freq == b.freq) {
            return a.num > b.num; // 频率相同,按整数大小升序
        }
        return a.freq > b.freq; // 按频率升序
    }
};

int main() {
    int nums[100], n, k;
    cout << "Enter the number of elements (n): ";
    cin >> n;

    cout << "Enter the elements: ";
    for (int i = 0; i < n; ++i) {
        cin >> nums[i];
    }

    cout << "Enter the value of k: ";
    cin >> k;

    // 使用哈希表统计每个整数的频率
    unordered_map<int, int> freqMap;
    for (int i = 0; i < n; ++i) {
        freqMap[nums[i]]++;
    }

    // 使用优先队列(最小堆)来存储频率和整数
    priority_queue<NumFreq, vector<NumFreq>, Compare> pq;

    // 将频率和整数加入优先队列
    for (const auto& entry : freqMap) {
        pq.push(NumFreq(entry.first, entry.second));
    }

    // 输出前k个整数
    cout << "The top " << k << " elements by frequency are: ";
    for (int i = 0; i < k; ++i) {
        if (pq.empty()) break;
        cout << pq.top().num << " ";
        pq.pop();
    }
    cout << endl;

    return 0;
}
算法和时间复杂度分析:
  • 使用了最小堆(这里使用c++标准库中的queue中的priority_queue类)对自定义节点的插入和删除算法时间复杂度为O(log2 n);
  • 使用了无序哈希表unordered_map容器,用哈希表来计数。
  • 关于优先队列具体的实现逻辑,我使用了一个比较器compare

priority_queue<NumFreq, vector<NumFreq>, Compare> pq

第一个参数NumFreq为结构体类型;第二个参数为装载若干结构体的容器,注意这里要引入头文件vector ,compare也是用结构体定义,用来重载运算符‘>’来实现pq内部排序逻辑。

个人心得:

个人感觉MarsCode最好用的一个地方就是在给定题目较长的时候可以通过思路提示代码提示来先对题目形成一个大概认知,分析测试用例和输出,这一部分的思考得到AI助手的提示,然后把更多的思考和精力放在算法实现和优化的具体逻辑上面,对于想要高效刷题的小白和友友们还是不错滴~

建议:可以让AI帮你写基本思框架,具体代码实现自己上手,又不会用的数据结构和算法可以直接问MarsCode,还是建议多自己思考,可以先自己分析题目,写好重要过程的注释,然后和AI回答作对比,对比一下有哪些地方是自己疏漏的,然后慢慢总结~


最后附上python代码

代码思路(python):

def solution(nums, k):
    # 统计每个元素的频率
    frequency = {}
    for num in nums:
        if num in frequency:
            frequency[num] += 1
        else:
            frequency[num] = 1
    
    # 按频率排序
    sorted_elements = sorted(frequency.items(), key=lambda item: item[1], reverse=True)
    
    #  选择前 k 个频率最高的元素
    top_k_elements = sorted_elements[:k]
    
    # 按升序排列
    top_k_elements.sort(key=lambda item: item[0])
    
    #  返回结果
    result = ','.join(str(item[0]) for item in top_k_elements)
    return result

if __name__ == "__main__":
    #  You can add more test cases here
    print(solution([1, 1, 1, 2, 2, 3], 2) == "1,2")
    print(solution([1], 1) == "1")