【LeetCode热题100】No.1——两数之和(Java)

大家好!今天开始我们正式开启 LeetCode 热题 100 系列的讲解,第一题就是经典的 "两数之和"。这道题不仅是 LeetCode 的入门必刷题,更是面试中高频出现的基础题,掌握它的解题思路,能帮我们建立对数组类问题的基本认知。接下来,我们就从题目分析、解法推导到代码实现,一步步把这道题吃透。

一、题目描述

首先,我们先明确题目要求(基于 LeetCode 官方原题):

  • 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
  • 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
  • 你可以按任意顺序返回答案。

示例

比如输入:nums = [2,7,11,15],target = 9

因为 2 + 7 = 9,所以返回 [0,1](数组下标从 0 开始)。

提示

  • 2 <= nums.length <= 10⁴(数组长度至少为 2,保证有解)
  • -10⁹ <= nums[i] <= 10⁹
  • -10⁹ <= target <= 10⁹
  • 只会存在一个有效答案

二、解题思路分析

解决这道题,我们可以从 "暴力解法" 入手,再逐步优化,理解不同解法的时间复杂度差异,这也是面试中面试官希望看到的思考过程。

1. 暴力解法:双重循环(入门思路)

思路逻辑

最直观的想法是:遍历数组中的每一个元素,对于当前元素 nums[i],再遍历它后面的所有元素 nums[j](j > i),判断 nums[i] + nums[j] 是否等于 target。如果等于,直接返回 [i, j]即可。

代码实现
java 复制代码
public class No1 {
    public static void main(String[] args) {
        int[] nums = {2,7,11,15};
        int target = 13;
        int[] result = Solution.twoSum(nums, target);
        System.out.println(Arrays.toString(result));
    }

    public static class Solution {
        public static int[] twoSum(int[] nums, int target) {
            for (int i = 0; i < nums.length; i++) {
                for (int j = 0; j < nums.length; j++) {
                    if(target == nums[i]+nums[j]){
                        return new int[]{i,j};
                    }
                }
            }
            return null;
        }
    }
}
复杂度分析
  • 时间复杂度:O (n²)。外层循环执行 n 次,内层循环平均执行 n/2 次,整体是二次方级别的操作,当数组长度很大(比如接近 10⁴)时,效率会很低。
  • 空间复杂度:O (1)。没有额外使用与数组长度相关的存储空间,只用到了几个变量。
缺点

暴力解法虽然思路简单,但时间复杂度太高,在面试中通常不会被接受,我们需要更高效的方法。

2. 优化解法:哈希表(推荐思路)

核心思路:用空间换时间

暴力解法的问题在于 "查找互补元素" 的过程太慢(每次都要遍历后面的元素)。如果我们能把 "查找互补元素" 的时间从 O (n) 降到 O (1),整体时间复杂度就能降到 O (n)。

这里的 "互补元素" 指的是:对于当前元素 nums[i],能和它组成 target 的元素是 complement = target - nums[i]。我们需要快速判断 complement 是否在数组中,并且获取它的下标。

哈希表(HashMap) 正好可以实现 "键值对" 的快速查找:

  • 把数组中的元素作为 "键(key)",元素的下标作为 "值(value)" 存入哈希表。
  • 遍历数组时,对于当前元素 nums[i],计算 complement = target - nums[i]。
  • 检查哈希表中是否存在 complement 这个键:
  • 如果存在,说明之前已经遍历过这个互补元素,直接返回 [哈希表中complement对应的值, i]。
  • 如果不存在,就把当前元素 nums[i] 和它的下标 i 存入哈希表,继续遍历下一个元素。
为什么能保证不重复?

因为我们是 "边遍历边存表",每次查找的都是已经遍历过的元素(即下标小于当前 i 的元素),所以不会出现同一个元素被重复使用的情况。

代码实现(Java 版)
java 复制代码
public class No1point1 {
    public static void main(String[] args) {
        int[] nums = {2, 7, 9, 11};
        int target = 11;
        int[] result = No1.Solution.twoSum(nums, target);
        System.out.println(Arrays.toString(result));
    }
    
    public int[] twoSum(int[] nums, int target) {
        // 初始化哈希表,key存数组元素,value存元素下标
        Map<Integer, Integer> map = new HashMap<>();
        int n = nums.length;
        // 遍历数组
        for (int i = 0; i < n; i++) {
            // 计算互补元素
            int complement = target - nums[i];
            // 检查互补元素是否在哈希表中
            if (map.containsKey(complement)) {
                // 存在则返回结果(互补元素的下标在前,当前下标在后)
                return new int[]{map.get(complement), i};
            }
            // 不存在则将当前元素和下标存入哈希表
            map.put(nums[i], i);
        }
        return null;
    }
}
复杂度分析
  • 时间复杂度:O (n)。只遍历了一次数组,每次哈希表的查找和插入操作都是 O (1),整体是线性时间。
  • 空间复杂度:O (n)。最坏情况下,需要把数组中所有元素都存入哈希表,存储空间与数组长度成正比。
优点

用少量的空间代价,换来了时间复杂度的大幅降低,是面试中的最优解,也是实际工程中推荐使用的方法。

三、测试案例验证

为了确保代码的正确性,我们可以用题目中的示例和一些边缘案例进行测试。

测试案例 1:基础案例

输入:nums = [2,7,11,15],target = 9

输出:[0,1]

测试案例 2:元素为负数

输入:nums = [3,2,4],target = 6

输出:[1,2]

测试案例 3:元素顺序不同

输入:nums = [3,3],target = 6

输出:[0,1]

四、总结

"两数之和" 虽然是一道简单题,但它涵盖了两个重要的解题思路:

  1. 暴力解法:适合入门理解问题,但效率低,不推荐实际使用。
  1. 哈希表解法:用空间换时间,是最优解,需要掌握哈希表的 "快速查找" 特性。

这道题的核心启示是:当遇到 "需要快速查找某个元素是否存在" 的场景时,优先考虑哈希表这种数据结构,它能极大提升查找效率。

下一篇我们会讲解 LeetCode 热题 100 的第二题,感兴趣的同学可以持续关注~如果有疑问,欢迎在评论区留言讨论!

相关推荐
编啊编程啊程2 小时前
gRPC从0到1系列【20】
java·rpc·kafka·dubbo·nio
Mingze03142 小时前
考研408之栈与队列学习
开发语言·c++·学习·考研·算法
艾醒2 小时前
探索大语言模型(LLM):大模型微调方式全解析
人工智能·算法
万邦科技Lafite4 小时前
如何对接API接口?需要用到哪些软件工具?
java·前端·python·api·开放api·电商开放平台
小许学java4 小时前
七大排序算法的基本原理
数据结构·算法·排序算法
1710orange4 小时前
java设计模式:静态代理模式
java·设计模式·代理模式
艾醒4 小时前
大模型面试题剖析:深入解析 Transformer 与 MoE 架构
人工智能·算法
我真的是大笨蛋5 小时前
开闭原则详解(OCP)
java·设计模式·性能优化·开闭原则·设计规范
编啊编程啊程5 小时前
gRPC从0到1系列【19】
java·spring boot·rpc·dubbo·nio