原理
题目目标:对输入的随机数进行去重并按升序排列。
核心思想:
- 去重:利用哈希表(
unordered_map
)统计每个数字的出现次数,哈希表的键(唯一性)自动实现去重。 - 排序:将去重后的键提取到动态数组(
vector
)中,并通过排序得到升序序列。
步骤
- 输入数据:读取整数
n
和n
个数字,存入数组nums
。 - 统计频率:遍历数组,使用哈希表统计每个数字的出现次数(键为数字,值为次数)。
- 提取键并排序:
- 将哈希表的键值对转换为动态数组
vec
。 - 对
vec
按键(即数字本身)升序排序。
- 将哈希表的键值对转换为动态数组
- 输出结果:遍历排序后的数组,输出去重且有序的数字。
图示法表示步骤(以输入 5 3 1 2 2 4
为例)
- 输入数据:
nums = [3, 1, 2, 2, 4]
- 哈希表统计:
键(数字) 值(次数) 3 1 1 1 2 2 4 1 - 提取键并排序:
- 初始
vec
(顺序可能不同):[{3,1}, {1,1}, {2,2}, {4,1}]
- 排序后
vec
:[{1,1}, {2,2}, {3,1}, {4,1}]
- 初始
- 输出结果:
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 个元素)。
总结
- 优点:
- 哈希表高效去重,排序逻辑简洁。
- 代码可读性强,适用于常规数据规模。
- 缺点:
- 哈希表内存占用较高(相比位图法)。
- 改进点:
- 若输入范围有限(如数字较小),可用数组替代哈希表优化空间。
- 直接使用
set
自动排序(但插入时间 O(logm) 可能更慢)。