题解:学而思编程 数字卡片

【题目来源】

学而思编程:数字卡片

【题目描述】

小猴收集了 \(n\) 张数字卡片,每一种数字卡片小猴恰好只有一张且都在 \(1\sim n\) 的范围内。

因为小猴加的猫咪贪玩,打翻了装着数字卡片的盒子,经过千辛万苦小猴终于把卡片捡起来装到盒子,但是发现少了一张数字卡片。

已知小猴现在盒子中的卡片分别是 \(a_1,a_2,\dots,a_{n-1}\),请你帮助小猴找出缺少的那一张数字卡片,并输出对应卡片上的数字。

【输入】

第一行包含一个整数 \(n\)

第二行包含 \(n-1\) 个整数 \(a_1,a_2,\dots,a_{n-1}\)

【输出】

一行一个整数,表示缺少的是哪一张数字卡片。

【输入样例】

5
4 3 2 1

【输出样例】

5

【核心思想】

  1. 问题分析:给定 \(1\)\(n\) 范围内的 \(n-1\) 个互不相同的数字,找出缺失的那个数字。这是一个标记数组问题,关键在于利用值域有限且唯一的特性,通过标记出现过的数字快速定位缺失值。

  2. 算法选择

    • 布尔标记数组f[i] 表示数字 \(i\) 是否出现在输入中
    • 线性扫描查找:遍历 \(1\)\(n\),找到未被标记的数字即为缺失值
  3. 关键步骤

    • 初始化:读取 \(n\)
    • 标记出现数字
      • 遍历 \(i\)\(1\)\(n-1\)
        • 读取 \(x\)
        • f[x] = true:标记数字 \(x\) 已出现
    • 查找缺失数字
      • 遍历 \(i\)\(1\)\(n\)
        • !f[i]\(i\) 未出现):输出 \(i\) 并结束
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\),两次线性遍历
    • 空间复杂度:\(O(n)\),布尔标记数组 f[1..n]
  5. 标记数组的核心思想

    • 值域确定性:数字范围固定为 \(1\)\(n\),且每个数字恰好出现 \(0\)\(1\) 次,适合用数组下标直接映射
    • 缺失即未标记:完整集合与给定集合的差集只有一个元素,扫描标记数组即可找到
    • 空间换时间:用 \(O(n)\) 空间实现 \(O(n)\) 时间,避免排序或求和的 \(O(n \log n)\)\(O(n)\) 但需处理溢出的方案
    • 扩展性:若值域过大可用 unordered_set,但本题值域适中,数组更高效
    • 适用于"有限值域内缺失元素查找"类问题,标记数组是最直观高效的解法

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
bool f[1000005];  // 布尔数组,标记出现的数字
int main()
{
    int n;
    cin >> n;  // 输入n
    for (int i = 1; i <= n - 1; i++)  // 输入n-1个数
    {
        int x;
        cin >> x;
        f[x] = true;  // 标记x出现过
    }
    for (int i = 1; i <= n; i++)  // 从1到n查找
    {
        if (!f[i])  // 如果i没出现过
        {
            cout << i;  // 输出缺失的数
            break;  // 找到后结束
        }
    }
    return 0;
}

【运行结果】

5
4 3 2 1
5
posted @ 2026-07-05 14:28  团爸讲算法  阅读(5)  评论(0)    收藏  举报