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

相关推荐
入门级前端开发2 小时前
vue集成xlsl实现前端表格导入导出
前端·javascript·vue.js
小二·2 小时前
Python Web 开发进阶实战:联邦学习平台 —— 在 Flask + Vue 中构建隐私保护的分布式 AI 训练系统
前端·python·flask
一人の梅雨2 小时前
中国制造网商品详情接口进阶实战:跨境场景下的差异化适配与问题攻坚
java·前端·javascript
无知的小菜鸡2 小时前
React:使用高阶组件实现vue中的路由守卫功能
前端·vue.js·react.js
xzl042 小时前
小智服务器intent_type 初始化为function_call过程
linux·前端·数据库
wuhen_n2 小时前
Webpack vs Vite:前端构建工具对比
前端·webpack·node.js·vite
EverydayJoy^v^2 小时前
RH134学习进程——四.归档和传输文件
服务器·前端·网络
muddjsv2 小时前
JavaScript 结合 Flex 布局的深度解析 (解锁前端布局新范式)
前端·javascript
卿着飞翔2 小时前
win11安装配置nginx并部署ruoyi前端
运维·前端·nginx