返回

LeetCode 268:巧妙解法,寻找丢失的数字

闲谈

在计算机科学中,丢失的数字问题是一个经典的面试题,它要求我们在给定一个包含从 0 到 n 的所有数字(除了一个数字)的数组中找到缺失的数字。这看似是一项艰巨的任务,但掌握了正确的策略,它可以被简化到一个高效的解决方案。本文将介绍解决 LeetCode 268 丢失数字问题的两种巧妙方法。

理解问题

LeetCode 268 丢失数字问题的如下:

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的数字。

例如,给定 nums = [3, 0, 1],输出应为 2。

方法 1:哈希表

哈希表是一种数据结构,它利用键值对来快速查找和检索元素。在解决 LeetCode 268 丢失数字问题时,我们可以利用哈希表来跟踪数组中出现的数字。

算法步骤:

  1. 创建一个大小为 n+1 的哈希表,其中 n 是给定数组 nums 的长度。
  2. 遍历数组 nums 中的每个元素,并将其作为键添加到哈希表中。
  3. 遍历范围 [0, n],检查每个数字是否作为键存在于哈希表中。
  4. 如果发现一个不存在于哈希表中的数字,则该数字即为丢失的数字。

代码示例:

def missing_number_hash(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    n = len(nums)
    hash_table = {}

    for num in nums:
        hash_table[num] = True

    for i in range(n+1):
        if i not in hash_table:
            return i

    return -1

方法 2:二分查找

二分查找是一种高效的搜索算法,它通过将搜索空间不断减半来快速找到目标元素。在解决 LeetCode 268 丢失数字问题时,我们可以使用二分查找来找到丢失的数字。

算法步骤:

  1. 对数组 nums 进行排序。
  2. 初始化两个指针 left 和 right,分别指向数组的开头和结尾。
  3. 在指针 left 和 right 之间执行二分查找:
    • 计算中点 mid = (left + right) // 2。
    • 如果 nums[mid] 等于 mid,则继续搜索右半部分,即 left = mid + 1。
    • 如果 nums[mid] 小于 mid,则丢失的数字一定出现在右半部分,即 left = mid + 1。
    • 如果 nums[mid] 大于 mid,则丢失的数字一定出现在左半部分,即 right = mid - 1。
  4. 继续二分查找,直到 left 和 right 相等。
  5. 此时的 left 和 right 指向丢失的数字。

代码示例:

def missing_number_binary_search(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    nums.sort()
    left, right = 0, len(nums)

    while left < right:
        mid = (left + right) // 2

        if nums[mid] == mid:
            left = mid + 1
        else:
            right = mid

    return left

分析

这两种方法都可以在 O(n) 的时间复杂度内找到丢失的数字。哈希表方法具有直接查找的优点,而二分查找方法则不需要额外的存储空间。

在实践中,当数组较小或哈希表操作成本较高时,哈希表方法可能更合适。当数组较大或哈希表操作成本较低时,二分查找方法可能更有效。

总结

通过使用哈希表或二分查找,我们可以高效地解决 LeetCode 268 丢失数字问题。这些方法提供了一种优雅且易于理解的解决方案,可以轻松应用于其他类似的问题。掌握这些算法不仅可以增强我们的编程技能,还可以为解决现实世界中的问题提供有价值的工具。