LeetCode 热题 100 - 第1题:两数之和

文章目录

    • 1.题目描述
      • [1.1 示例](#1.1 示例)
      • [1.2 提示](#1.2 提示)
      • [1.3 进阶](#1.3 进阶)
    • [2. 解法分析](#2. 解法分析)
      • [2.1 方法一:暴力枚举(双重循环)](#2.1 方法一:暴力枚举(双重循环))
      • [2.2 方法二:哈希表(先存后找)](#2.2 方法二:哈希表(先存后找))
      • [2.3 方法三:哈希表(边存边找,最优解)](#2.3 方法三:哈希表(边存边找,最优解))
    • [3. 三种方法对比](#3. 三种方法对比)
    • [4. 总结与感悟](#4. 总结与感悟)

原题链接:1. 两数之和


1.题目描述

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

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。你可以按任意顺序返回答案。

1.1 示例

示例 1:

复制代码
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]。

示例 2:

复制代码
输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

复制代码
输入:nums = [3,3], target = 6
输出:[0,1]

1.2 提示

  • 2 <= nums.length <= 10^4
  • -10^9 <= nums[i] <= 10^9
  • -10^9 <= target <= 10^9
  • 只会存在一个有效答案

1.3 进阶

你可以想出一个时间复杂度小于 O(n^2) 的算法吗?


2. 解法分析

2.1 方法一:暴力枚举(双重循环)

思路

最直观的方法:遍历数组中的每一个元素 nums[i],再遍历它之后的所有元素 nums[j],判断两数之和是否等于 target

代码实现

java 复制代码
public int[] twoSum(int[] nums, int target) {
    int[] result = new int[2];
    int length = nums.length;
    for (int i = 0; i < length; i++) {
        // 从 i+1 开始,避免使用同一个元素两次
        for (int j = i + 1; j < length; j++) {
            if (nums[i] + nums[j] == target) {
                result[0] = i;
                result[1] = j;
                return result; // 题目保证只有一个有效答案,直接返回
            }
        }
    }
    return result;
}

复杂度分析

复杂度 量级 说明
时间复杂度 O(n²) 两层循环,最坏情况下每个元素都会被遍历 n 次
空间复杂度 O(1) 只使用了固定大小的额外空间(result 数组和循环变量)

优点:简单直接,不需要额外数据结构。

缺点:当数组长度很大(如 n = 10^4)时,O(n²) 会非常慢(约 1 亿次操作)。


2.2 方法二:哈希表(先存后找)

思路

为了降低查找 "target - nums[i]" 的时间,我们可以使用哈希表(HashMap)存储每个元素的值和它的下标。

第一步:遍历数组,将所有元素存入哈希表。

第二步:再次遍历数组,对于每个 nums[i],检查 target - nums[i] 是否在哈希表中,并且下标不能与 i 相同。

代码实现

java 复制代码
public int[] twoSum2(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    // 第一遍:存入所有元素及其下标
    for (int i = 0; i < nums.length; i++) {
        map.put(nums[i], i);
    }
    // 第二遍:查找符合条件的另一个数
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            int index = map.get(complement);
            if (i != index) { // 不能是同一个元素
                return new int[]{i, index};
            }
        }
    }
    return new int[0];
}

复杂度分析

复杂度 量级 说明
时间复杂度 O(n) 两个循环各 O(n),哈希表操作平均 O(1),整体 O(n)
空间复杂度 O(n) 哈希表最多存储 n 个键值对

优点:时间复杂度降为 O(n),适合数据量大的场景。

缺点:需要额外的 O(n) 空间。


2.3 方法三:哈希表(边存边找,最优解)

思路

其实不需要两次循环。我们可以在遍历数组的同时,将当前元素需要的 "互补数" 在哈希表中查找,如果找到了就直接返回;如果没找到,就把当前元素存入哈希表,供后面的元素匹配。

这样一次遍历即可完成,而且天然避免了使用同一个元素两次(因为查找时当前元素还未存入哈希表)。

代码实现

java 复制代码
public int[] twoSum3(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        // 检查哈希表中是否存在需要的互补数
        if (map.containsKey(complement)) {
            return new int[]{map.get(complement), i};
        }
        // 没找到,则将当前元素存入,供后续元素匹配
        map.put(nums[i], i);
    }
    return new int[0];
}

复杂度分析

复杂度 量级 说明
时间复杂度 O(n) 一次循环,哈希表操作 O(1)
空间复杂度 O(n) 最坏情况下哈希表存储 n-1 个元素

优点:时间最优(只需一次遍历),代码简洁优雅。

注意:虽然空间复杂度仍是 O(n),但实际存储的元素数量可能略少于方法二(最坏情况相同)。


3. 三种方法对比

方法 时间复杂度 空间复杂度 适用场景
暴力枚举 O(n²) O(1) 数组长度很小(如 n ≤ 1000)
哈希表(先存后找) O(n) O(n) 通用,但多一次循环
哈希表(边存边找) O(n) O(n) 推荐,代码最简洁,效率最高

4. 总结与感悟

通过这道题,我们可以得到几点重要的收获:

  1. 用空间换时间是常见优化手段

    暴力法不需要额外空间,但时间慢。引入哈希表后,时间复杂度从 O(n²) 降到 O(n),虽然多用了 O(n) 的空间,但对于现代计算机来说通常是值得的。

  2. 哈希表的查找效率极高

    在需要频繁查找 "某个元素是否存在" 或 "获取某个元素对应的值" 时,哈希表的平均 O(1) 时间复杂度几乎是不可替代的。

  3. 一次遍历的技巧

    "边存边找" 的方法非常巧妙,它利用了哈希表存储的是已经遍历过的元素这一特性,避免了使用同一个元素两次,同时减少了一次循环。这种 "延迟存入" 的思路在很多题目中都可以复用。

  4. 注意避免的坑

    • 不能使用同一个元素两次 → 在边存边找中,当前元素还没有存入,自然就不会匹配到自己。
    • 题目保证只有一个有效答案 → 所以找到后可以立即返回,不需要继续查找。

希望这篇博客对你有所帮助,也欢迎大家在评论区交流讨论!如果觉得有用,不妨点个赞支持一下 !感谢,共勉,祝好!😊

相关推荐
white-persist1 小时前
逆向入门经典题:从 IDA 反编译坑点到 Python 解题详细分析解释
c语言·开发语言·数据结构·python·算法·逆向·安全架构
炽烈小老头1 小时前
【每天学习一点算法 2026/04/23】盛最多水的容器
学习·算法
Ailan_Anjuxi1 小时前
手写数字识别零基础实战:基于PyTorch的CNN完整拆解
算法·图像识别
jiucaixiuyang1 小时前
散户如何使用手机T0算法?
算法·量化·t0
阿Y加油吧2 小时前
算法二刷复盘:LeetCode 79 单词搜索 & 131 分割回文串(Java 回溯精讲)
java·算法·leetcode
徐新帅2 小时前
4164:【GESP2512七级】学习⼩组
算法
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 101. 对称二叉树 | C++ DFS 极简递归模板
c++·leetcode·深度优先
北顾笙9802 小时前
day30-数据结构力扣
数据结构·算法·leetcode
爱写代码的倒霉蛋2 小时前
天梯赛经验总结(细节篇)
经验分享·算法