青训营X豆包MarsCode 代码详解 | 豆包MarsCode AI 刷题

90 阅读5分钟

找单独的数

题目描述

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

要求:

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

测试样例

样例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 ≤ cards.length ≤ 1001
  • 0 ≤ cards[i] ≤ 1000
  • 班级人数为奇数
  • 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次

思路

这道题初看很简单,但是思路解法很多,题目就是要找到数字卡片中唯一出现一次的数,难度在于如何“高效”的找出他

思路 1: 异或运算

基本原理

  • 使用异或运算的性质。对于任何数字 x,有以下特点:

    • x ^ x = 0(任何数与自己异或为 0)
    • x ^ 0 = x(任何数与 0 异或为该数本身)
    • 异或操作是可交换和结合的,即 a ^ b = b ^ aa ^ (b ^ c) = (a ^ b) ^ c

实现步骤

  1. 初始化一个变量 unique 为 0。
  2. 遍历数组中的每个数字,将其与 unique 进行异或运算。
  3. 最后 unique 中的值即为只出现一次的那个数字。

时间复杂度:O(n)

空间复杂度:O(1)

思路 2: 使用 HashMap

基本原理

  • 利用哈希表(HashMap)来统计每个数字出现的次数。

实现步骤

  1. 创建一个空的 HashMap。
  2. 遍历数组,将每个数字作为键,出现的次数作为值更新到 HashMap 中。
  3. 遍历 HashMap,找到出现次数为 1 的键。

时间复杂度:O(n)

空间复杂度:O(n)

思路 3: 排序法

基本原理

  • 通过对数组进行排序,然后遍历检查连续的数字。

实现步骤

  1. 对数组进行排序(例如使用快速排序或归并排序)。
  2. 遍历排序后的数组,检查相邻的元素。
  3. 找到与前后元素都不相等的数字,即为唯一出现的数字。

时间复杂度:O(n log n)(由于排序)

空间复杂度:O(1)(如果使用原地排序)

思路 4: 计数数组

基本原理

  • 当已知数字的范围不大(如 0 到 1000)时,可以使用固定大小的数组进行次数统计。

实现步骤

  1. 创建一个大小为 1001 的计数数组(根据题目约束)。
  2. 遍历输入数组,统计每个数字出现的次数。
  3. 遍历计数数组,查找出现次数为 1 的索引。

时间复杂度:O(n)

空间复杂度:O(1)(固定大小的数组)

总结与对比

1. 异或运算法

优点:

  • 时间复杂度 O(n),只需遍历一次数组,效率非常高。
  • 空间复杂度 O(1),不需要额外的存储空间。

缺点:

  • 只有在知道所有数字都成对出现的情况下才有效,适用于特定条件。
  • 对于不熟悉位运算的开发者,可能理解上存在一些难度。

适用场景:

  • 经典的只出现一次的数字问题。
  • 需要高效处理大规模数据的场合。

2. HashMap法

优点:

  • 逻辑简单明了,易于理解和实现。
  • 可以方便地统计同学中多个独特数字的出现次数,只需扩展判断条件即可。

缺点:

  • 时间复杂度 O(n),但由于哈希表的开销可能会略微增加常数因子。
  • 空间复杂度 O(n),在元素很多时需要较多的存储空间。

适用场景:

  • 处理复杂的数据统计问题,可以快速扩展功能。
  • 需要多次查找或统计次数的场合。

3. 排序法

优点:

  • 方法简单,易于实现并理解。
  • 适合有层级关系的数字,使用排序可以直观地找出重复元素。

缺点:

  • 时间复杂度 O(n log n),由于排序,效率较低。
  • 需要额外的空间(在某些实现中)来存放排序后的数组。

适用场景:

  • 当数组的大小处于较小的范围时,可能表现良好。
  • 需要额外信息时(如首次出现的位置、频率等)可以考虑。

4. 计数数组法

优点:

  • 时间复杂度 O(n),通过计数可以快速查找唯一数字。
  • 空间复杂度 O(1)(固定大小),适合处理已知范围的整数。

缺点:

  • 仅适用于数字范围已知且较小的情况(如 0 到 1000)。
  • 不适合处理负数或超出设定范围的数字。

适用场景:

  • 有固定的数字范围且可能出现大量相同数字的情况。
  • 整数的范围被限制到某个小范围时表现优秀。

总结对比

方法时间复杂度空间复杂度优点缺点适用场景
异或运算法O(n)O(1)效率高,空间开销小可能不易理解,适用于特定条件简单的只出现一次的问题
HashMap法O(n)O(n)易于理解,可扩展存储开销大,依赖哈希表的特性数据统计,较复杂的事件
排序法O(n log n)O(1)或O(n)实现简单,直观效率低,额外的排序开销需要查找、比较的情况
计数数组法O(n)O(1)快速查找,固定大小的空间仅适用于已知小范围的数字,不支持负数或更多范围条件有固定范围且频率统计的场景