题解:学而思编程 数数字
【题目来源】
学而思编程:数数字
【题目描述】
给定 \(n\) 个正整数\(a_1,a_2,\dots,a_n\),请你找出这些正整数中一共有多少个互不相同的正整数。
例如:\(3\),\(1\),\(2\),\(1\),\(5\) 中一共有 \(4\) 个互不相同的正整数,分别是 \(1\),\(2\),\(3\),\(5\)。
【输入】
第一行一个整数 \(n\);
第二行 \(n\) 个正整数 \(a_1,a_2,\dots,a_n\)。
【输出】
一行一个整数,表示互不相同的正整数的数量。
【输入样例】
3
1 2 3
【输出样例】
3
【核心思想】
-
问题分析:给定 \(n\) 个正整数,统计其中互不相同的正整数个数。这是一个频次统计 + 去重计数问题,关键在于记录每个数字是否出现过,然后统计出现过的数字种类数。
-
算法选择:
- 计数数组:
box[x]记录数字 \(x\) 出现的次数 - 线性扫描去重:遍历值域,统计出现次数大于 \(0\) 的数字个数
- 计数数组:
-
关键步骤:
- 初始化:读取 \(n\)
- 统计频次:
- 遍历 \(i\) 从 \(1\) 到 \(n\):
- 读取 \(x\)
box[x]++:标记数字 \(x\) 出现
- 遍历 \(i\) 从 \(1\) 到 \(n\):
- 统计不同数字个数:
cnt = 0- 遍历 \(i\) 从 \(1\) 到 \(10^6\)(值域):
- 若
box[i] > 0:cnt++(该数字出现过)
- 若
- 输出
cnt
-
时间/空间复杂度:
- 时间复杂度:\(O(n + V)\),\(V\) 为值域大小(\(10^6\)),输入统计 \(O(n)\),扫描值域 \(O(V)\)
- 空间复杂度:\(O(V)\),计数数组
box[1..V]
-
计数数组的核心思想:
- 值域有限性:题目隐含值域不大(\(1 \leq a_i \leq 10^6\)),可用数组直接映射
- 出现即标记:无需关心具体次数,只需知道是否出现过(
> 0),但计数数组同时支持更复杂的频次查询 - 线性扫描值域:遍历固定值域统计非零位置,得到不同数字的种类数
- 替代方案:若值域大或未知,可用
set或sort + unique,但计数数组在值域适中时效率最高 - 适用于"有限值域内去重计数"类问题,计数数组实现简单、查询高效
【解题思路】

【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6; // 数组大小
int n, x, box[N + 10]; // n: 数字个数, x: 临时变量, box: 计数数组
int main()
{
cin >> n; // 输入数字个数
for (int i = 1; i <= n; i++) // 输入n个数字
{
cin >> x;
box[x]++; // 统计每个数字出现的次数
}
int cnt = 0; // 不同数字的个数
for (int i = 1; i <= 1e6; i++) // 遍历所有可能的值
{
if (box[i] > 0) // 如果这个数字出现过
{
cnt++; // 计数器加1
}
}
cout << cnt << endl; // 输出不同数字的个数
return 0;
}
【运行结果】
3
1 2 3
3
浙公网安备 33010602011771号