LeetCode Hot100(1/100)——1. 两数之和 (Two Sum)

文章目录

      • 题目描述
      • 解法一:暴力枚举法 (Brute Force)
        • [1. 思路解析](#1. 思路解析)
        • [2. 流程图 (Mermaid)](#2. 流程图 (Mermaid))
        • [3. Java 代码实现](#3. Java 代码实现)
        • [4. 复杂度分析](#4. 复杂度分析)
      • [解法二:哈希表法 (Hash Map) ------ **推荐解法**](#解法二:哈希表法 (Hash Map) —— 推荐解法)
        • [1. 思路解析](#1. 思路解析)
        • [2. 状态演变图解](#2. 状态演变图解)
        • [3. 逻辑流程图 (Mermaid)](#3. 逻辑流程图 (Mermaid))
        • [4. Java 代码实现](#4. Java 代码实现)
        • [5. 复杂度分析](#5. 复杂度分析)
      • 总结对比

题目描述

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

示例:

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

输出:[0,1]

解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]


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

1. 思路解析

这是最直观的思路。我们需要找到两个数,不妨设为 xy

我们可以通过两层循环来遍历数组:

  • 第一层循环 选取第一个数 x (索引为 i)。
  • 第二层循环 选取第二个数 y (索引为 j)。
  • 判断 nums[i] + nums[j] 是否等于 target
  • 注意:题目要求不能使用同一个元素,所以内层循环从 i + 1 开始。
2. 流程图 (Mermaid)







开始
外层循环 i 从 0 到 n-1
i < n ?
内层循环 j 从 i+1 到 n-1
j < n ?
numsi + numsj == target ?
找到答案! 返回 {i, j}
j++
i++
未找到答案 (理论上不会到达)

3. Java 代码实现
java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int n = nums.length;
        // 第一层循环
        for (int i = 0; i < n; i++) {
            // 第二层循环,从 i+1 开始,避免重复和自身相加
            for (int j = i + 1; j < n; j++) {
                // 判断和是否为 target
                if (nums[i] + nums[j] == target) {
                    return new int[]{i, j};
                }
            }
        }
        return new int[0]; // 题目保证有解,此处仅为语法完整
    }
}
4. 复杂度分析
  • 时间复杂度 : O ( N 2 ) O(N^2) O(N2)。最坏情况下,我们需要遍历几乎所有的元素对。对于较大的数组,这种方法会非常慢。
  • 空间复杂度 : O ( 1 ) O(1) O(1)。只使用了常数个变量存储索引。

解法二:哈希表法 (Hash Map) ------ 推荐解法

1. 思路解析

暴力法的瓶颈在于:对于每个 x,我们需要遍历数组来寻找是否存在 target - x。这个查找过程是 O ( N ) O(N) O(N) 的。

我们可以利用 哈希表 (HashMap) 这种数据结构,利用其 O ( 1 ) O(1) O(1) 的查找时间复杂度来优化算法。

  • 我们在遍历数组的过程中,将元素的值和它的索引存入哈希表。
  • 核心逻辑 :在遍历当前元素 num 时,先检查哈希表中是否存在 target - num(即补数)。
    • 如果存在,说明之前已经遍历过那个数了,直接返回两个索引。
    • 如果不存在,将当前元素 num 和它的索引 i 存入哈希表,供后面的元素查找。
2. 状态演变图解

假设 nums = [2, 7, 11, 15], target = 9

步骤 当前索引 (i) 当前数值 (num) 需要寻找的补数 (target - num) 哈希表状态 (Check -> Put) 结果
1 0 2 9 - 2 = 7 Map中含7吗? No 。 Put {2: 0} 继续
2 1 7 9 - 7 = 2 Map中含2吗? Yes (index 0)。 找到! 返回 [0, 1]
3. 逻辑流程图 (Mermaid)



开始
初始化 HashMap
遍历数组 nums
获取当前元素 nums/i
计算补数: complement = target - nums/i
Map中包含 key 为

complement 吗?
获取 Map.get/complement

作为第一个索引
返回 {mapIndex, i}
结束
将 {nums/i : i}

存入 Map

4. Java 代码实现
java 复制代码
import java.util.HashMap;
import java.util.Map;

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 创建哈希表,Key存放数值,Value存放索引
        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];
    }
}
5. 复杂度分析
  • 时间复杂度 : O ( N ) O(N) O(N)。我们只遍历了包含 N N N 个元素的数组一次。在表中进行每次查找花费 O ( 1 ) O(1) O(1) 的时间。
  • 空间复杂度 : O ( N ) O(N) O(N)。最坏情况下,我们需要将 N N N 个元素都存入哈希表中(例如数组中没有匹配对,或者匹配对在最后两个)。

总结对比

特性 暴力枚举法 哈希表法 (最优)
核心思想 双重循环遍历 空间换时间 (查表)
时间复杂度 O ( N 2 ) O(N^2) O(N2) (慢) O ( N ) O(N) O(N) (快)
空间复杂度 O ( 1 ) O(1) O(1) (省空间) O ( N ) O(N) O(N) (耗空间)
代码简洁度 简单 适中
适用场景 N 非常小的时候 通用场景,尤其是大数据量
相关推荐
江畔柳前堤3 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore4 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考5 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX6 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面7 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号7 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽7 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI7 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者9 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者9 小时前
【征程6】校准量化中HistogramObserver解析
算法