返回

巧解剑指 Offer 03:数组中重复的数字

Android

在编程迷宫中寻找重复数据:剑指 Offer 03 解密

在浩瀚无垠的编程世界中,寻找重复数据就像解开一团乱麻,令人头疼不已。剑指 Offer 03 抛出了这样一个挑战,要求我们在一个井然有序的整数数组中揪出那个调皮捣蛋、重复出现的数字。今天,我们将踏上这段智力冒险,挥舞代码利剑斩断谜团,用智慧明灯照亮答案。

哈希表的锋利武器

哈希表,数据结构界的魔术师,以其迅雷不及掩耳的查找速度闻名遐迩。它的奥秘在于将数据存储在根据其密钥进行快速检索的桶中。对于这个问题,我们将数组中的每个数字作为密钥,并将其出现的次数存储为对应的值。

原地交换的巧妙法宝

题目中提到,数组中的数字是有序的。这一特性为我们提供了一个妙不可言的解决方案:原地交换。我们依次遍历数组,检查每个数字在哈希表中的出现次数。如果出现次数超过 1,则表明该数字重复出现。此时,我们将其与数组末尾的数字进行交换,然后缩小数组的搜索范围。

算法攻略

  1. 初始化一个哈希表,以数字为密钥,出现次数为值。
  2. 遍历数组中的每个数字,并将其添加到哈希表中。如果数字已经存在,则递增其出现次数。
  3. 再次遍历数组,对于每个数字:
    • 如果其在哈希表中的出现次数大于 1,则表示该数字重复出现。
    • 将其与数组末尾的数字交换。
    • 将数组的搜索范围缩小到交换点之前。
  4. 重复步骤 3,直到数组中不再有重复的数字。
  5. 返回重复出现的数字。

代码示例

def find_duplicate(nums):
  """
  找出数组中重复的数字。

  参数:
    nums: 一个有序的整数数组。

  返回:
    重复出现的数字。
  """

  # 初始化哈希表
  hash_table = {}

  # 第一次遍历,统计每个数字出现的次数
  for num in nums:
    if num not in hash_table:
      hash_table[num] = 0
    hash_table[num] += 1

  # 第二次遍历,查找重复的数字
  for i in range(len(nums)):
    if hash_table[nums[i]] > 1:
      # 找到重复的数字,将其与数组末尾的数字交换
      nums[i], nums[len(nums) - 1] = nums[len(nums) - 1], nums[i]
      # 缩小搜索范围
      nums = nums[:len(nums) - 1]
      # 返回重复的数字
      return nums[i]

  # 数组中没有重复的数字
  return -1

总结

通过这趟剑指 Offer 03 的寻宝之旅,我们不仅掌握了寻找重复数字的技巧,更领略了算法思维的魅力。哈希表的快速检索和原地交换的巧妙结合,展现了计算机科学中巧思与实用的完美平衡。愿这篇文章成为你编程宝库中的一颗明珠,照亮你日后的探索之路。

常见问题解答

  1. 为什么使用哈希表而不是排序算法?

    • 哈希表可以更快地查找数字,而排序算法需要对数组进行排序,这在数组较大时会非常耗时。
  2. 为什么原地交换而不是创建新数组?

    • 原地交换节省了时间和空间,因为我们不需要创建和复制新数组。
  3. 如果数组中有重复的数字,算法会返回哪一个?

    • 算法将返回第一个重复出现的数字。
  4. 如果数组中没有重复的数字,算法会返回什么?

    • 算法将返回 -1。
  5. 算法的复杂度是多少?

    • 算法的时间复杂度为 O(n),其中 n 是数组的长度。空间复杂度为 O(n),因为我们使用哈希表来存储每个数字的出现次数。