你想要用 C++ 实现"找出数列中重复的元素,并统计每个重复元素的出现个数",我会提供两种实用的实现方法:一种是基础的双重循环法(适合新手理解核心逻辑),另一种是更高效的哈希表法(适合实际开发),并详细解释每种方法的思路和代码。
核心需求分析
- 输入:一个整数数列(数组)。
- 输出:列出所有出现次数 ≥ 2 的元素,以及每个元素的具体出现次数。
- 要求:逻辑清晰,兼顾新手理解和实际开发效率。
实现方法
方法 1:基础双重循环法(新手友好)
思路:
- 遍历数组中的每个元素,作为"基准元素"。
- 对每个基准元素,再次遍历数组,统计其出现次数。
- 用一个标记数组记录已经统计过的元素,避免重复输出(比如元素 5 统计一次后,后续再遇到 5 就跳过)。
- 只输出出现次数 ≥ 2 的元素及其次数。
cpp
#include <iostream>
#include <cstring> // 用于memset函数
using namespace std;
// 找出重复元素并统计个数(双重循环法)
void findDuplicatesBasic(int arr[], int n) {
// 标记数组:记录是否已统计过该元素(初始化为false)
bool isCounted[n];
memset(isCounted, false, sizeof(isCounted)); // 初始化标记数组
cout << "重复元素及个数:" << endl;
for (int i = 0; i < n; ++i) {
// 如果该元素已统计过,跳过
if (isCounted[i]) continue;
int count = 1; // 至少出现1次(当前元素本身)
for (int j = i + 1; j < n; ++j) {
if (arr[j] == arr[i]) {
count++;
isCounted[j] = true; // 标记该位置元素已统计
}
}
// 只输出出现次数≥2的元素
if (count >= 2) {
cout << "元素 " << arr[i] << ":出现 " << count << " 次" << endl;
}
}
}
int main() {
// 测试数组
int arr[] = {5, 2, 9, 5, 1, 2, 5, 6, 2, 9};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "原数组:";
for (int i = 0; i < n; ++i) {
cout << arr[i] << " ";
}
cout << endl;
findDuplicatesBasic(arr, n);
return 0;
}
输出结果:
原数组:5 2 9 5 1 2 5 6 2 9
重复元素及个数:
元素 5:出现 3 次
元素 2:出现 3 次
元素 9:出现 2 次
方法 2:哈希表法(高效推荐)
思路:
- 使用 C++ 标准库的
unordered_map(哈希表),键为数组元素,值为该元素的出现次数。 - 遍历数组一次,用哈希表统计每个元素的出现次数(时间复杂度 O(n)O(n)O(n))。
- 遍历哈希表,输出出现次数 ≥ 2 的元素及其次数。
- 优点:效率远高于双重循环(双重循环为 O(n2)O(n^2)O(n2)),适合大规模数据。
cpp
#include <iostream>
#include <unordered_map> // 哈希表头文件
using namespace std;
// 找出重复元素并统计个数(哈希表法)
void findDuplicatesHash(int arr[], int n) {
// 哈希表:key=数组元素,value=出现次数
unordered_map<int, int> countMap;
// 第一步:遍历数组,统计每个元素的出现次数
for (int i = 0; i < n; ++i) {
countMap[arr[i]]++; // 元素出现一次,计数+1
}
// 第二步:遍历哈希表,输出重复元素
cout << "重复元素及个数:" << endl;
for (auto& pair : countMap) { // auto 自动推导类型,pair是键值对
int num = pair.first; // 元素值
int count = pair.second; // 出现次数
if (count >= 2) {
cout << "元素 " << num << ":出现 " << count << " 次" << endl;
}
}
}
int main() {
int arr[] = {5, 2, 9, 5, 1, 2, 5, 6, 2, 9};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "原数组:";
for (int i = 0; i < n; ++i) {
cout << arr[i] << " ";
}
cout << endl;
findDuplicatesHash(arr, n);
return 0;
}
输出结果:
原数组:5 2 9 5 1 2 5 6 2 9
重复元素及个数:
元素 5:出现 3 次
元素 2:出现 3 次
元素 9:出现 2 次
代码关键说明
-
双重循环法:
isCounted数组用于标记已统计的元素,避免重复输出(比如数组中有多个 5,只统计第一个 5 的次数)。memset函数用于将标记数组初始化为false(需包含<cstring>头文件)。- 缺点:效率低,数组元素越多,耗时越明显。
-
哈希表法:
unordered_map是 C++ 高效的哈希表容器,查找和插入的平均时间复杂度为 O(1)O(1)O(1)。countMap[arr[i]]++是核心:如果元素不存在,会自动插入并初始化值为 0,然后 +1;如果已存在,直接 +1。auto& pair简化了类型声明(等价于pair<int, int>& pair),pair.first是键(元素值),pair.second是值(次数)。
扩展:支持字符串数组
只需将哈希表的键类型改为 string,即可统计字符串的重复次数:
cpp
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
void findDuplicateStrings(string arr[], int n) {
unordered_map<string, int> countMap;
for (int i = 0; i < n; ++i) {
countMap[arr[i]]++;
}
cout << "重复字符串及个数:" << endl;
for (auto& pair : countMap) {
if (pair.second >= 2) {
cout << "字符串 \"" << pair.first << "\":出现 " << pair.second << " 次" << endl;
}
}
}
int main() {
string strArr[] = {"apple", "banana", "apple", "orange", "banana", "apple"};
int n = sizeof(strArr) / sizeof(strArr[0]);
findDuplicateStrings(strArr, n);
return 0;
}
输出结果:
重复字符串及个数:
字符串 "apple":出现 3 次
字符串 "banana":出现 2 次
总结
- 双重循环法 :逻辑简单、无需额外库,适合新手理解核心思想,但效率低(O(n2)O(n^2)O(n2)),仅适用于小规模数据。
- 哈希表法 :基于
unordered_map,效率高(O(n)O(n)O(n)),是实际开发中的首选,支持整型、字符串等多种类型。 - 核心要点:统计重复元素的关键是"计数+去重",哈希表通过键的唯一性天然实现去重,双重循环则需手动标记已统计元素。