返回

化繁为简:LeetCode上的两数之和问题

见解分享

LeetCode 两数之和:解锁高效解决之道

作为一名热衷于 LeetCode 的编程爱好者,你一定遇到过看似简单却需要独特思维方式才能解决的问题。今天,让我们深入探讨 LeetCode 上广受关注的题目:两数之和。

题意简介

给你一个整数数组 nums 和一个整数目标值 target,找出数组中两数之和等于 target 的索引对。需要注意的是,数组中的元素不可重复使用。

暴力求解:双重遍历

最直接的解法是双重遍历数组,比较每一个可能的元素组合。虽然这种方法保证了正确性,但时间复杂度为 O(n²),效率较低。对于海量数据而言,这显然不可行。

哈希表优化:O(n) 的解法

为了提高效率,我们可以引入哈希表。哈希表的特点是查找时间复杂度为 O(1),非常适合用于寻找特定的元素。

我们的解题思路如下:

  1. 创建一个哈希表,key 为数组元素,value 为元素索引。
  2. 遍历数组,对于每个元素,计算其与 target 的差值 diff
  3. 如果哈希表中存在 diff,则说明找到了和为 target 的两数。返回它们的索引。
  4. 如果哈希表中不存在 diff,则将当前元素及其索引放入哈希表中。

这种哈希表解法的平均时间复杂度为 O(n),显著优于暴力求解方法。

代码示例(哈希表解法):

def twoSum(nums, target):
    hashtable = {}

    for i, num in enumerate(nums):
        diff = target - num
        if diff in hashtable:
            return [hashtable[diff], i]
        else:
            hashtable[num] = i

    return None  # 如果找不到两数之和,则返回 None

进一步优化:一步到位

我们可以对哈希表解法进行进一步优化,将查找和插入合并到一步。具体步骤如下:

  1. 遍历数组,对于每个元素,计算其与 target 的差值 diff
  2. 如果哈希表中存在 diff,则说明找到了和为 target 的两数。返回它们的索引。
  3. 如果哈希表中不存在 diff,则检查哈希表中是否存在当前元素。
    • 如果存在,说明当前元素可以与自身组成和为 target 的两数。返回它们各自的索引。
    • 如果不存在,则将当前元素及其索引放入哈希表中。

这种优化后的解法的平均时间复杂度仍为 O(n),但代码简洁性和效率都有所提升。

代码示例(优化后的解法):

def twoSumOptimized(nums, target):
    hashtable = {}

    for i, num in enumerate(nums):
        diff = target - num
        if diff in hashtable:
            return [hashtable[diff], i]
        elif num not in hashtable:
            hashtable[num] = i

    return None  # 如果找不到两数之和,则返回 None

实例解析

nums = [2, 7, 11, 15]target = 9 为例。

暴力求解:

[2, 7]
[2, 11]
[7, 2]
[7, 11]
[11, 2]
[11, 7]

哈希表解法:

  1. 遍历数组,并插入哈希表:
    • key = 2, value = 0
    • key = 7, value = 1
    • key = 11, value = 2
    • key = 15, value = 3
  2. 计算 diff = 9 - 2 = 7,在哈希表中找到 diff,返回索引 [0, 1]

优化后的解法:

  1. 遍历数组:
    • 计算 diff = 9 - 2 = 7,在哈希表中找到 diff,返回索引 [0, 1]
  2. 由于哈希表中没有 key = 7 的元素,因此不进行进一步检查。

总结

LeetCode 上的两数之和问题看似简单,但求解方法却多种多样。通过使用哈希表,我们可以将时间复杂度优化到 O(n),大大提高了效率。进一步的优化还可以简化代码,提升可读性和维护性。

希望这篇教程能帮助各位刷题爱好者更深入地理解 LeetCode 两数之和问题的解法,并激发你们更多创新解题思路。

常见问题解答

  1. 为什么哈希表解法的时间复杂度为 O(n),而不是 O(n²)?
    答:因为哈希表可以让我们在常数时间内查找元素,因此即使要遍历数组,时间复杂度也保持为 O(n)。

  2. 为什么优化后的解法不会错过任何可能的解?
    答:因为优化后的解法在插入元素时也会检查它本身是否可以与 target 组成两数之和。

  3. 两数之和问题还有哪些其他解决方法?
    答:除了暴力求解和哈希表解法外,还可以使用双指针方法和二分查找方法。

  4. 为什么在优化后的解法中使用 elif 而不是 else
    答:为了避免重复检查。如果使用 else,那么当哈希表中不存在 diff 时,它会先检查 num 是否在哈希表中,然后再插入 num。使用 elif 可以直接插入 num,避免了重复检查。

  5. 如何处理数组中可能存在重复元素的情况?
    答:在这种情况下,需要修改哈希表中的值,将索引存储为一个列表,而不是单个值。