卡码网50. 随机数排序(第七期模拟笔试)

原理

题目目标:对输入的随机数进行去重并按升序排列。
核心思想

  1. 去重:利用哈希表(unordered_map)统计每个数字的出现次数,哈希表的键(唯一性)自动实现去重。
  2. 排序:将去重后的键提取到动态数组(vector)中,并通过排序得到升序序列。

步骤

  1. 输入数据:读取整数 n 和 n 个数字,存入数组 nums
  2. 统计频率:遍历数组,使用哈希表统计每个数字的出现次数(键为数字,值为次数)。
  3. 提取键并排序
    • 将哈希表的键值对转换为动态数组 vec
    • 对 vec 按键(即数字本身)升序排序。
  4. 输出结果:遍历排序后的数组,输出去重且有序的数字。

图示法表示步骤(以输入 5 3 1 2 2 4 为例)

  1. 输入数据nums = [3, 1, 2, 2, 4]
  2. 哈希表统计
    键(数字)值(次数)
    31
    11
    22
    41
  3. 提取键并排序
    • 初始 vec(顺序可能不同):[{3,1}, {1,1}, {2,2}, {4,1}]
    • 排序后 vec[{1,1}, {2,2}, {3,1}, {4,1}]
  4. 输出结果1 2 3 4

代码关键行注释

unordered_map<int, int> umap;  
for (int i = 0; i < n; i++) umap[nums[i]]++;  // 统计频率并去重  

vector<pair<int, int>> vec(umap.begin(), umap.end());  // 转为动态数组  
sort(vec.begin(), vec.end());  // 按键(数字)升序排序  

for (int i = 0; i < vec.size(); i++) cout << vec[i].first << " ";  // 输出结果  

完整代码

#include <algorithm>  
#include <iostream>  
#include <utility>  
#include <vector>  
#include <unordered_map>  

using namespace std;  

int main() {  
    int n;  
    cin >> n;  
    vector<int> nums(n);  
    for (int i = 0; i < n; i++) cin >> nums[i];  

    unordered_map<int, int> umap;  
    for (int i = 0; i < n; i++) umap[nums[i]]++;  

    vector<pair<int, int>> vec(umap.begin(), umap.end());  
    sort(vec.begin(), vec.end());  

    for (int i = 0; i < vec.size(); i++) cout << vec[i].first << " ";  
    return 0;  
}  

时间复杂度

  • 时间复杂度
    • 统计频率:O(n)(哈希表插入平均 O(1))。
    • 排序:O(mlogm),其中 m 是去重后的数字数量(m≤n)。
    • 总体:O(n+mlogm),最坏情况 O(nlogn)。
  • 空间复杂度:O(n)(哈希表和动态数组存储最多 n 个元素)。

总结

  1. 优点
    • 哈希表高效去重,排序逻辑简洁。
    • 代码可读性强,适用于常规数据规模。
  2. 缺点
    • 哈希表内存占用较高(相比位图法)。
  3. 改进点
    • 若输入范围有限(如数字较小),可用数组替代哈希表优化空间。
    • 直接使用 set 自动排序(但插入时间 O(logm) 可能更慢)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值