青训营刷题笔记:唯一的数字卡片 | 豆包MarsCode AI刷题

58 阅读3分钟

青训营刷题笔记:唯一的数字卡片

问题描述

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

要求

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

解题思路

  1. 异或操作的特性:

    • 对于任意整数 xx,满足 x⊕x=0x \oplus x = 0 和 x⊕0=xx \oplus 0 = x。
    • 异或操作满足交换律和结合律,因此一组数字通过异或操作后,相同的数字会两两抵消为 0,最终只剩下唯一一个不重复的数字。
  2. 时间复杂度和空间复杂度:

    • 遍历数组一次完成所有计算,因此时间复杂度为 O(n)O(n)。
    • 使用一个变量存储结果,不需要额外空间,空间复杂度为 O(1)O(1)。

算法实现

代码

def solution(cards):
    # 初始化结果为0
    result = 0
    
    # 遍历卡片列表,并进行异或运算
    for card in cards:
        result ^= card
    
    # 返回唯一不重复的数字
    return result

# 测试用例
if __name__ == "__main__":
    print(solution([1, 1, 2, 2, 3, 3, 4, 5, 5]) == 4)  # 输出:4
    print(solution([0, 1, 0, 1, 2]) == 2)              # 输出:2
    print(solution([7, 3, 3, 7, 10]) == 10)            # 输出:10

测试样例

样例1

  • 输入: cards = [1, 1, 2, 2, 3, 3, 4, 5, 5]
  • 输出: 4
  • 解释: 唯一没有配对的数字是 4

样例2

  • 输入: cards = [0, 1, 0, 1, 2]
  • 输出: 2
  • 解释: 唯一没有配对的数字是 2

样例3

  • 输入: cards = [7, 3, 3, 7, 10]
  • 输出: 10
  • 解释: 唯一没有配对的数字是 10

复杂度分析

  1. 时间复杂度:

    • 遍历数组仅需一次,时间复杂度为 O(n)O(n)。
  2. 空间复杂度:

    • 使用常数级别的空间存储异或结果,空间复杂度为 O(1)O(1)。

总结

该解法充分利用了异或操作的性质,实现了时间复杂度为 O(n)O(n) 和空间复杂度为 O(1)O(1) 的高效算法,满足了题目的优化要求。这道题的核心在于找到一个数组中唯一不重复的数字,其余数字均出现两次。解题关键在于使用异或运算的特性,设计出高效且优化的算法。

异或操作特性

  1. 自反性:x⊕x=0x \oplus x = 0,即相同的数异或为 0。
  2. 单位元:x⊕0=xx \oplus 0 = x,即一个数与 0 异或不变。
  3. 交换律和结合律:异或可以改变顺序或分组而结果不变。因此,对于任意序列中成对出现的数字,异或运算会将它们抵消为 0,剩下的唯一一个数字就是答案。

算法设计

通过一次遍历,用一个变量保存异或结果,逐个将数组中的每个数字异或到变量中。最终,这个变量保存的值即为唯一的数字。这种方法时间复杂度为 O(n)O(n),因为只需遍历一次数组;空间复杂度为 O(1)O(1),只使用常量空间存储结果。

测试与优化

测试样例验证了算法在不同情况下的有效性,例如 [1, 1, 2, 2, 3, 3, 4, 5, 5] 的输出为 4,而 [7, 3, 3, 7, 10] 输出为 10,均正确满足题意。

总结

通过异或运算,本算法不仅实现了时间复杂度 O(n)O(n) 和空间复杂度 O(1)O(1),还展现了数学运算在优化算法设计中的重要作用,充分体现了高效和简洁的算法思想。