青训营X豆包MarsCode 技术训练营第一课 | 豆包MarsCode AI 刷题

42 阅读3分钟

问题描述

在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。

要求:

  1. 设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。
  2. 尽量减少额外空间的使用,以体现你的算法优化能力。

问题分析

在一个班级中,卡片上数字的分布特点是:

  • 只有一个数字出现了一次。
  • 其他所有数字均出现两次。

我们需要在 时间复杂度 O(n) 的约束下找出这个唯一的数字,同时尽量减少额外空间的使用。

解题思路

解决这个问题的关键在于利用数字的 异或运算 (XOR) 。异或运算的性质非常适合这种问题:

  1. 交换律:a⊕b=b⊕aa \oplus b = b \oplus a
  2. 结合律:a⊕(b⊕c)=(a⊕b)⊕ca \oplus (b \oplus c) = (a \oplus b) \oplus c
  3. 自反性:a⊕a=0a \oplus a = 0
  4. 与 0 的关系:a⊕0=aa \oplus 0 = a

基于上述性质,若对所有数字进行异或运算:

  • 两个相同的数字会因自反性变为 0。
  • 最终结果是唯一出现的数字,因为它没有与其他数字配对。

算法设计

  1. 初始化一个变量 result 为 0。
  2. 遍历整个数组,对每个数字执行异或操作 result=result⊕numresult = result \oplus num。
  3. 遍历结束后,result 即为唯一出现的数字。

此算法的时间复杂度为 O(n)O(n),因为我们只需遍历数组一次;空间复杂度为 O(1)O(1),因为只用了常数空间。

实现代码(Python)

def find_unique_number(nums):
    result = 0
    for num in nums:
        result ^= num
    return result

# 示例测试
nums = [2, 3, 5, 3, 2]
print("唯一的数字是:", find_unique_number(nums))  # 输出:5

算法验证

示例 1

输入:2,3,5,3,22, 3, 5, 3, 2
过程:

  • 初始 result=0result = 0
  • result⊕2=2result \oplus 2 = 2
  • 2⊕3=12 \oplus 3 = 1
  • 1⊕5=41 \oplus 5 = 4
  • 4⊕3=74 \oplus 3 = 7
  • 7⊕2=57 \oplus 2 = 5
    输出:5(唯一数字)

示例 2

输入:1,1,7,8,81, 1, 7, 8, 8
过程:

  • 初始 result=0result = 0
  • result⊕1=1result \oplus 1 = 1
  • 1⊕1=01 \oplus 1 = 0
  • 0⊕7=70 \oplus 7 = 7
  • 7⊕8=157 \oplus 8 = 15
  • 15⊕8=715 \oplus 8 = 7
    输出:7(唯一数字)

时间与空间复杂度分析

  1. 时间复杂度

    • 遍历数组只需 O(n)O(n),其中 nn 是数组的长度。
  2. 空间复杂度

    • 算法使用了一个变量 result,其空间复杂度为 O(1)O(1)。

优化与扩展

  • 输入校验:可以提前检查数组是否为空或包含无效值。
  • 扩展性:此算法可推广到类似问题,如寻找数组中两个只出现一次的数字。

总结

利用异或运算巧妙解决问题,可以极大提升效率并减少额外空间使用。这种算法不仅高效,还具有优雅的数学逻辑基础,非常适合面试和实际开发场景。