1. 找单独的数-cpp | 豆包MarsCode AI 刷题

1 阅读2分钟

题目解析

在班级发放数字卡片这个场景中,我们面临一个独特的算法问题:如何在一组数字中找出唯一一个只出现一次的数字。这个问题虽然看似简单,但要在满足时间复杂度O(n)和最小空间复杂度的约束下实现最优解,需要仔细思考和巧妙的设计。

关键约束

从题目中可以提取以下约束条件:

  1. 1 ≤ cards.length ≤ 1001 (数组长度限制)
  2. 0 ≤ cards[i] ≤ 1000 (卡片上的数字范围)
  3. 班级人数为奇数(因为只有一个数字出现一次,其他都出现两次)
  4. 除了一个数字出现一次外,其他数字都出现两次

解题思路

  1. 方法一:哈希表统计

    • 遍历数组统计每个数字出现的次数
    • 找出只出现一次的数字
    • 时间复杂度 O(n),空间复杂度 O(n)
  2. 方法二: 排序后比较法

    • 思路:先排序,然后比较相邻元素
    • 优点:无需额外空间
    • 缺点:时间复杂度为O(nlogn),不满足要求
  3. 方法三:异或运算(最优解)

    • 利用异或运算的特性:

      • a ⊕ a = 0
      • a ⊕ 0 = a
      • 满足交换律和结合律
    • 对数组所有元素进行异或运算

    • 最终结果就是只出现一次的数字

    • 时间复杂度 O(n),空间复杂度 O(1)

代码实现(选用最优解)

#include <iostream>
#include <vector>

int solution(std::vector<int> cards) {
  // 用于存储异或结果
  int result = 0;

  // 遍历数组中的每个数字
  for (int num : cards) {
    // 利用异或运算的特性:
    // 1. a⊕a=0:相同的数异或结果为0
    // 2. a⊕0=a:任何数与0异或等于它本身
    // 3. 异或运算满足交换律和结合律
    result ^= num;
  }

  // 最终结果就是只出现一次的数字
  return result;
}

代码详解

  1. 初始化

    • 创建变量 result 并初始化为0,用于存储异或运算的结果
  2. 核心算法

    • 遍历数组中的每个数字
    • 将每个数字与 result 进行异或运算
    • 由于相同的数字异或为0,最终只出现一次的数字会保留下来
  3. 返回结果

    • 返回 result,即为只出现一次的数字

算法正确性证明

以示例 [1,1,2,2,3,3,4,5,5] 为例:

  1. result = 0
  2. 0⊕1 = 1
  3. 1⊕1 = 0
  4. 0⊕2 = 2
  5. 2⊕2 = 0
  6. 0⊕3 = 3
  7. 3⊕3 = 0
  8. 0⊕4 = 4
  9. 4⊕5 = 4⊕5
  10. (4⊕5)⊕5 = 4

最终得到只出现一次的数字 4。

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组长度
  • 空间复杂度:O(1),只使用了常数额外空间