hot100_LeetCode 1 | 两数之和(Two Sum)

🎯 LeetCode 1 | 两数之和(Two Sum)

“两数之和”的双指针解法和哈希解法,以双指针为主。


🔍 问题描述

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

你可以假设:

  • 每种输入只会对应一个有效答案;
  • 不能使用同一个元素两次;
  • 可以按任意顺序返回答案。

🔗 原题链接:LeetCode 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. 创建一个二维数组 indexNums,记录每个元素的值及其原始索引;
  2. 对这个数组按照数值进行排序;
  3. 使用双指针分别从头(left)和尾(right)遍历数组,寻找和为 target 的两个数;
  4. 如果找到,则返回其对应的原始索引;
  5. 注意不能使用相同的元素(即不能 left == right);
优势分析:
  • 排序后利用双指针可以快速查找;
  • 时间复杂度为 O(n log n),优于暴力枚举的 O(n²);
  • 同时保留原索引信息,方便最终结果返回。

✨ 方法二:哈希法

思路简述:

判断一个元素是否出现在一个集合中,用哈希,哈希的键为元素

思路:遍历数组nums 判断target-nums[cur]是否在哈希表内,若在返回cur 和target-nums[cur]对应的索引

如何构造哈希:不在哈希表内,则把nums[i]作为k,i作为v存入哈希内

✅ 示例代码(Java 实现)

方法一:排序 + 双指针法

import java.util.Arrays;

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 记录值及对应的原始索引
        int[][] indexNums = new int[nums.length][2];
        for (int i = 0; i < nums.length; i++) {
            indexNums[i][0] = nums[i]; // 存值
            indexNums[i][1] = i;       // 存索引
        }

        // 按照数值升序排序
        Arrays.sort(indexNums, (a, b) -> a[0] - b[0]);

        int left = 0;
        int right = nums.length - 1;

        while (left < right) {
            int sum = indexNums[left][0] + indexNums[right][0];

            if (sum < target) {
                left++;
            } else if (sum > target) {
                right--;
            } else {
                return new int[]{indexNums[left][1], indexNums[right][1]};
            }
        }

        // 理论上不会走到这里
        throw new IllegalArgumentException("No two sum solution");
    }
}

方法二:哈希法

class Solution {

    //使用哈希表
        
    public int[] twoSum(int[] nums, int target) {
        int[] res = new int[2];
        if(nums == null || nums.length == 0){
            return res;
        }
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            int temp = target - nums[i];   // 遍历当前元素,并在map中寻找是否有匹配的key
            if(map.containsKey(temp)){
                res[1] = i;
                res[0] = map.get(temp);
                break;
            }
            map.put(nums[i], i);    // 如果没找到匹配对,就把访问过的元素和下标加入到map中
        }
        return res;
    }
}

🧩 小贴士(Tips)

⚠️ 注意事项

  • 不能使用相同的元素:比如 nums = [3, 2, 4],如果 target = 6,虽然 nums[0] + nums[0] == 6,但这是不允许的。
  • 不能修改原数组:保存原始索引非常重要,因为排序会打乱顺序;
  • 异常处理:建议在找不到解时抛出异常,而不是直接返回空数组;
  • 效率优化:排序加双指针的时间复杂度是 O(n log n),适用于大多数场景。

📊 复杂度分析

操作时间复杂度空间复杂度
排序O(n log n)O(n)
双指针查找O(n)O(1)
总体O(n log n)O(n)

🎯 总结

本题的关键在于:

  • 掌握排序 + 双指针的技巧;
  • 理解索引保存的重要性;
  • 注意不能使用相同元素;
  • 学会异常处理和边界判断;

🚀 拓展思考

  • 能否用哈希表实现?时间复杂度可优化到 O(n),空间换时间的经典案例。
  • 如何将“两数之和”扩展为“三数之和”或“四数之和”?
  • 若允许重复使用相同元素如何处理?

📖 相关推荐


💬 互动一下:

你第一次做“两数之和”这道题时遇到什么挑战了吗?欢迎留言分享你的经历👇


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值