LeetCode 第一题

LeetCode 第一题(两数之和)用哈希表解法的核心是以空间换时间,将查找目标值的时间从 O (n) 降到 O (1),整体时间复杂度 O (n),空间复杂度 O (n)。

核心思路

遍历数组时,用哈希表(对象 / Map) 存储已遍历元素的值:对应索引 ;对当前元素nums[i],计算目标差值target - nums[i],若差值存在于哈希表中,直接返回[哈希表差值的索引, i];若不存在,将当前元素和索引存入哈希表,继续遍历。

可直接运行的 JS 代码(Map 版,推荐)

复制代码
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    const map = new Map(); // 哈希表:key=数值,value=索引
    for (let i = 0; i < nums.length; i++) {
        const diff = target - nums[i];
        if (map.has(diff)) { // 差值已存在,找到解
            return [map.get(diff), i];
        }
        map.set(nums[i], i); // 未找到,存入当前元素
    }
    return []; // 题目保证有解,此句可省略
};

简化版(对象版)

复制代码
var twoSum = function(nums, target) {
    const obj = {};
    for (let i = 0; i < nums.length; i++) {
        const diff = target - nums[i];
        if (diff in obj) {
            return [obj[diff], i];
        }
        obj[nums[i]] = i;
    }
};

关键细节

  1. 为什么不用先存全部元素 :边遍历边存,避免同一元素被重复使用(如target=6,nums=[3,3],先查再存可正确匹配两个 3);
  2. Map vs 普通对象:Map 支持任意类型键,且不会与对象原型属性冲突,处理负数 / 0 更安全,推荐使用;
  3. 题目特性 :题目明确有且仅有一个解,无需处理多解 / 无解情况,遍历到解可直接返回。

对比暴力解法

解法 时间复杂度 空间复杂度 核心逻辑
暴力双重 for O(n²) O(1) 遍历所有元素两两组合
哈希表法 O(n) O(n) 哈希表快速查找目标差值

两数之和(哈希解法)核心边界测试用例

覆盖重复元素、负数、目标值为 0、单元素相邻匹配四大高频边界,附测试结果 + 代码适配性说明(上述 Map / 对象解法均完美适配)

1. 重复元素(核心易错题)
  • 用例:nums = [3,3], target = 6
  • 结果:[0,1]
  • 关键:边查边存 ,先判断diff=3是否在哈希表(初始空),再存入第一个 3,遍历第二个 3 时可匹配到第一个 3 的索引,避免同一元素重复使用。
2. 包含负数
  • 用例:nums = [2,7,-1,15], target = 6
  • 结果:[2,3]
  • 关键:Map / 对象对负数键无处理问题,比数组下标法更适配负数场景。
3. 目标值为 0
  • 用例:nums = [-1,0,1,2], target = 0
  • 结果:[0,2]
  • 关键:哈希表可正常存储 / 查找0和负数值,无特殊处理逻辑。
4. 相邻元素匹配(基础边界)
  • 用例:nums = [2,7,11,15], target = 9
  • 结果:[0,1]
  • 关键:遍历第二个元素 7 时,diff=2已在哈希表中,直接返回结果,是最基础的正常场景。
5. 元素为 0 的重复匹配
  • 用例:nums = [0,4,0,3], target = 0
  • 结果:[0,2]
  • 关键:哈希表按首次出现存储索引,后续匹配可精准拿到前置索引。

测试代码(可直接运行)

将上述用例代入解法,快速验证结果:

复制代码
var twoSum = function(nums, target) {
    const map = new Map();
    for (let i = 0; i < nums.length; i++) {
        const diff = target - nums[i];
        if (map.has(diff)) return [map.get(diff), i];
        map.set(nums[i], i);
    }
    return [];
};

// 测试用例执行
console.log(twoSum([3,3],6)); // [0,1]
console.log(twoSum([2,7,-1,15],6)); // [2,3]
console.log(twoSum([-1,0,1,2],0)); // [0,2]
console.log(twoSum([2,7,11,15],9)); // [0,1]
console.log(twoSum([0,4,0,3],0)); // [0,2]

边界坑点总结

  1. 若先存后查 ,会导致重复元素用例失败(如[3,3]会匹配到同一索引);

  2. 用普通对象时,若数值为__proto__(极端情况)会冲突,Map 可彻底避免,推荐优先使用;

  3. 无需处理数组长度 < 2 的情况,题目明确有且仅有一个解,输入均为有效用例。

    const map = new Map();

    map.set('a', 5);
    map.set('b', 7);
    map.set('c', 9);

    console.log(map.get('a')); // 5
    console.log(map.has('b')); // true

相关推荐
她说可以呀11 小时前
Vue插槽
前端·javascript·vue.js
qq_4480111611 小时前
Vue + Jinja2两套模版与法冲突造成undefinedError
前端·javascript·vue.js
aixingpan11 小时前
aixingpan.cn API开发文档:前端查询夏令时和时区接口指南
前端·php
2601_9583529012 小时前
23.5×19mm 换掉一整条音频链?|A-68 集成了什么:ADC / DAC / 24.576MHz 时钟 / AEC / 波束降噪,主控仅需 6 根线
前端·音视频·ai降噪·回声消除·语音模块
志尊宝12 小时前
AI原生前端开发(039):AI辅助的Nuxt 4全栈开发
前端·vue.js·ai-native
FRing0313 小时前
JavaScript入门到精通三十二(深拷贝、浅拷贝、递归函数)
开发语言·前端·javascript
excel14 小时前
双 Token 与前端使用 Crypto 公私钥鉴权换 Token,哪种方案更好?
前端·后端
外收内放14 小时前
Python基础语法练习题(73)
java·前端·python
风骏时光牛马14 小时前
面向复杂场景的大模型应用落地与能力优化实践
前端
小小善后师14 小时前
我做了个病历归档小程序,被 AI 识别的"最后一公里"狠狠上了一课
前端