题解:298 素数元素的统计
题目
问题分析
本题要求在一个整数数组中,统计满足以下两个条件的元素个数:
- 该元素本身是素数。
- 该元素在数组中出现的次数也是素数。
需要特别注意:
- 需要分别判断数组元素和该元素的出现次数是否为素数。
- 例如,数组
[1, 2, 3, 2, 5, 7, 7, 7, 5]中,元素2出现了两次,而7出现了三次。这两次和三次都需要判断是否为素数。
解题思路
-
辅助函数:判断素数
使用一个辅助函数isPrime,判断一个整数是否为素数:- 小于等于 1 的数不是素数。
- 从
2遍历到sqrt(n),如果n能被任何一个数整除,则不是素数。 - 如果遍历完成没有发现因数,则该数为素数。
-
统计数组中每个元素的出现次数
使用unordered_map数据结构来统计每个元素的频率,其中键为数组中的元素,值为该元素的出现次数。 -
判断条件
遍历频率表中的每一对键值对(num, freq):- 检查
num是否为素数。 - 检查
freq是否为素数。 - 如果两个条件均满足,则计数器加一。
- 检查
-
输出结果
返回符合条件的元素总数。
代码解析
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
// 判断一个数是否为素数
bool isPrime(int n) {
if (n <= 1) return false; // 小于等于1不是素数
for (int i = 2; i * i <= n; ++i) { // 遍历到sqrt(n)
if (n % i == 0) return false; // 存在因数,非素数
}
return true; // 无因数,素数
}
int solution(vector<int> a) {
unordered_map<int, int> frequency; // 统计每个元素的出现次数
for (int num : a) {
++frequency[num]; // 频率加一
}
int count = 0; // 计数器
for (const auto& pair : frequency) {
int num = pair.first; // 元素
int freq = pair.second; // 频率
// 检查元素和其频率是否都为素数
if (isPrime(num) && isPrime(freq)) {
++count; // 符合条件的元素计数
}
}
return count;
}
int main() {
cout << (solution({1, 2, 3, 2, 5, 7, 7, 7, 5}) == 3) << endl;
cout << (solution({1, 4, 6, 8, 10, 12}) == 0) << endl;
cout << (solution({3, 3, 3, 5, 5, 5, 5}) == 1) << endl;
return 0;
}
样例说明
样例 1
输入:a = [1, 2, 3, 2, 5, 7, 7, 7, 5]
- 频率统计:
1: 出现 1 次2: 出现 2 次3: 出现 1 次5: 出现 2 次7: 出现 3 次
- 检查素数条件:
2是素数,且出现 2 次也是素数。3是素数,且出现 1 次(非素数)。5是素数,且出现 2 次也是素数。7是素数,且出现 3 次也是素数。
- 满足条件的元素有:
2、5、7,总计 3 个。
输出:3
样例 2
输入:a = [1, 4, 6, 8, 10, 12]
- 频率统计:每个元素出现 1 次。
- 检查素数条件:
- 所有元素均不是素数,直接返回 0。
输出:0
- 所有元素均不是素数,直接返回 0。
样例 3
输入:a = [3, 3, 3, 5, 5, 5, 5]
- 频率统计:
3: 出现 3 次5: 出现 4 次
- 检查素数条件:
3是素数,且出现 3 次也是素数。5是素数,但出现 4 次(非素数)。
输出:1
复杂度分析
-
时间复杂度
- 遍历数组统计频率:
O(n) - 遍历频率表检查素数:
O(k * sqrt(m)),其中k为频率表中键值对数,m为键或频率的最大值。 - 总时间复杂度:
O(n + k * sqrt(m))。
- 遍历数组统计频率:
-
空间复杂度
使用unordered_map存储频率,空间复杂度为O(k)。