[leetcode 1]给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数[力扣]

两数之和问题详解:从暴力到哈希表的优化之路

引言

两数之和问题是算法学习中的经典入门题目,也是面试中高频出现的基础题型。作为LeetCode的第一道题目,它不仅考察了对数组操作的基本理解,更蕴含了从暴力解法到高效算法的优化思维。本文将详细解析这一问题的多种解法,重点介绍如何利用哈希表将时间复杂度从O(n²)降至O(n),并通过实例验证算法的正确性。

问题描述

题目要求 :给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。

约束条件

  • 2 ≤ nums.length ≤ 10⁴
  • -10⁹ ≤ nums[i] ≤ 10⁹
  • -10⁹ ≤ target ≤ 10⁹
  • 只会存在一个有效答案

示例

  • 示例1:输入:nums = [2,7,11,15], target = 9 → 输出:[0,1](解释:2+7=9)
  • 示例2:输入:nums = [3,2,4], target = 6 → 输出:[1,2](解释:2+4=6)
  • 示例3:输入:nums = [3,3], target = 6 → 输出:[0,1](解释:3+3=6)

解题思路

方法一:暴力枚举法(Brute Force)

思路解析

暴力枚举法是最直观的解决方案,通过双重循环遍历数组中的每一个元素,检查每对元素的和是否等于目标值。具体步骤如下:

  1. 外层循环遍历数组中的每个元素nums[i](索引i从0到n-1)
  2. 内层循环遍历当前元素之后的所有元素nums[j](索引j从i+1到n-1)
  3. nums[i] + nums[j] == target,则返回[i, j]
代码实现
python 复制代码
def twoSum(nums, target):
    n = len(nums)
    for i in range(n):
        for j in range(i+1, n):
            if nums[i] + nums[j] == target:
                return [i, j]
    return []  # 题目保证有解,此句可省略
复杂度分析
  • 时间复杂度:O(n²),其中n为数组长度。双重循环导致最坏情况下需要检查n(n-1)/2对元素
  • 空间复杂度:O(1),只使用了常数级别的额外空间
局限性

虽然暴力法简单易懂,但在数组长度较大时(如接近10⁴),O(n²)的时间复杂度会导致运算时间显著增加,可能出现超时问题。因此需要更高效的算法。

方法二:哈希表优化法(Hash Table)

思路解析

哈希表(Hash Table)是解决查找问题的高效数据结构,其平均查找时间复杂度为O(1)。通过空间换时间的策略,我们可以将查找互补数的过程优化为常数时间:

  1. 创建一个空的哈希表(字典),用于存储已遍历元素的值和对应的索引
  2. 遍历数组中的每个元素nums[i],计算与目标值的差值complement = target - nums[i]
  3. 检查complement是否在哈希表中:
    • 若存在,则返回[哈希表[complement], i]
    • 若不存在,则将当前元素nums[i]及其索引i存入哈希表
  4. 继续遍历直到找到解
核心优势
  • 只需遍历一次数组,时间复杂度降至O(n)
  • 通过哈希表实现互补数的快速查找,避免了内层循环
  • 自然处理重复元素(如示例3),因为后出现的元素会查找先前存入的元素
代码实现
python 复制代码
def twoSum(nums, target):
    # 创建哈希表存储已遍历元素的值和索引
    num_map = {}
    for i, num in enumerate(nums):
        # 计算互补数
        complement = target - num
        # 检查互补数是否已存在于哈希表中
        if complement in num_map:
            # 若存在,返回互补数的索引和当前索引
            return [num_map[complement], i]
        # 若不存在,将当前元素存入哈希表
        num_map[num] = i
    return []  # 题目保证有解,此句可省略
复杂度分析
  • 时间复杂度:O(n),其中n为数组长度。只需遍历一次数组,每次哈希表操作平均为O(1)
  • 空间复杂度:O(n),最坏情况下需要存储n-1个元素到哈希表中

示例详解

示例1:nums = [2,7,11,15], target = 9

  1. 遍历i=0,num=2:complement=9-2=7。哈希表为空,存入{2:0}
  2. 遍历i=1,num=7:complement=9-7=2。哈希表中存在2,返回[0,1]

示例2:nums = [3,2,4], target = 6

  1. 遍历i=0,num=3:complement=6-3=3。哈希表为空,存入{3:0}
  2. 遍历i=1,num=2:complement=6-2=4。哈希表中不存在4,存入{3:0, 2:1}
  3. 遍历i=2,num=4:complement=6-4=2。哈希表中存在2,返回[1,2]

示例3:nums = [3,3], target = 6

  1. 遍历i=0,num=3:complement=6-3=3。哈希表为空,存入{3:0}
  2. 遍历i=1,num=3:complement=6-3=3。哈希表中存在3,返回[0,1]

进阶思考

算法优化空间

  • 早期终止:哈希表方法已实现一次遍历完成查找,无法进一步降低时间复杂度
  • 空间优化:在空间受限场景下,可结合排序+双指针法(但会改变索引,需额外存储原始索引)

类似问题扩展

  • 三数之和:找出数组中所有和为0的三元组(需去重,复杂度O(n²))
  • 四数之和:类似三数之和,增加一层循环(复杂度O(n³))
  • 两数之和 II - 输入有序数组:可使用双指针法实现O(n)时间和O(1)空间

哈希表实现细节

  • 冲突处理:Python字典使用开放寻址法处理哈希冲突,保证查找效率
  • 键值选择:本题以元素值为键,索引为值,适合查找值对应的索引

结论

两数之和问题展示了数据结构对算法效率的巨大影响。通过哈希表的应用,我们成功将时间复杂度从O(n²)优化至O(n),体现了"空间换时间"的经典算法设计思想。在实际开发中,应根据问题约束选择合适的算法:

  • 小规模数据或空间受限场景:可考虑暴力法
  • 大规模数据或时间敏感场景:哈希表方法是更优选择

掌握这种优化思维,对于解决更复杂的算法问题具有重要意义。建议读者进一步研究哈希表的实现原理及其在其他问题中的应用,如子数组和问题、频率统计问题等。

完整代码

python 复制代码
def twoSum(nums, target):
    """
    两数之和:找出数组中和为目标值的两个整数的索引
    
    参数:
        nums: List[int] - 整数数组
        target: int - 目标和
        
    返回:
        List[int] - 两个整数的索引列表
    """
    num_map = {}  # 存储已遍历元素的值:索引
    for index, num in enumerate(nums):
        complement = target - num
        if complement in num_map:
            return [num_map[complement], index]
        num_map[num] = index
    return []  # 题目保证有解,实际不会执行到此

# 测试示例
if __name__ == "__main__":
    print(twoSum([2,7,11,15], 9))   # 输出: [0, 1]
    print(twoSum([3,2,4], 6))       # 输出: [1, 2]
    print(twoSum([3,3], 6))         # 输出: [0, 1]
相关推荐
沐怡旸2 小时前
【算法--链表】138.随机链表的复制--通俗讲解
算法·面试
anlogic2 小时前
Java基础 9.10
java·开发语言·算法
程序员奈斯2 小时前
Python深度学习:NumPy数组库
python·深度学习·numpy
薛定谔的算法2 小时前
JavaScript单链表实现详解:从基础到实践
数据结构·算法·leetcode
yongche_shi2 小时前
第二篇:Python“装包”与“拆包”的艺术:可迭代对象、迭代器、生成器
开发语言·python·面试·面试宝典·生成器·拆包·装包
深度学习lover2 小时前
<数据集>yolo梨幼果识别数据集<目标检测>
python·yolo·目标检测·计算机视觉·数据集
CoovallyAIHub2 小时前
CostFilter-AD:用“匹配代价过滤”刷新工业质检异常检测新高度! (附论文和源码)
深度学习·算法·计算机视觉
幻奏岚音2 小时前
《数据库系统概论》第一章 初识数据库
数据库·算法·oracle
你好,我叫C小白2 小时前
贪心算法(最优装载问题)
算法·贪心算法·最优装载问题