首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

LeetCode 题解 | 1.两数之和(最优解)

  • 25-04-18 17:00
  • 3589
  • 5444
juejin.cn

题目——1.两数之和

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

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

示例 1:

ini
代码解读
复制代码
输入: nums = [2,7,11,15], target = 9 输出: [0,1] 解释: 因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

ini
代码解读
复制代码
输入: nums = [3,2,4], target = 6 输出: [1,2]

示例 3:

ini
代码解读
复制代码
输入: nums = [3,3], target = 6 输出: [0,1]

 

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

二、小白题解(正是本人)

js
代码解读
复制代码
/**  * @param {number[]} nums  * @param {number} target  * @return {number[]}  */ var twoSum = function(nums, target) {     for(let i=0;ilength;i++){         for(let j=i+1;jlength;j++){             if(nums[i]+nums[j]===target){                 return [i,j];             }         }     } };

这个解题思路有很多缺点—— 时间复杂度高、没有异常处理、看上去像作者自己写的......

总之就是一个暴力题解,我们在最坏的情况下是N(O2)N(O2)N(O2)的时间复杂度,会将nums中的所有元素组合遍历知道找到符合条件的两个元素的下标,那么有没有更好的解法呢?

三、有的兄弟,肯定有的(时间复杂度上的最优解)

js
代码解读
复制代码
/** * @param {number[]} nums * @param {number} target * @return {number[]} */ function twoSum(nums, target) { const numMap = {}; for (let i = 0; i < nums.length; i++) { const complement = target - nums[i]; if (complement in numMap) { return [numMap[complement], i]; } numMap[nums[i]] = i; } return []; }

这个解法用到了哈希表,这里我们并不需要去详细研究哈希表是个什么东西,我们这里可以把哈希表理解为一个容器,里面的数据可以拿出来和我们想要的目标数据对比,每次对比是N(O)N(O)N(O)的复杂度。

我们来看题解的主体

js
代码解读
复制代码
for (let i = 0; i < nums.length; i++) { const complement = target - nums[i]; if (complement in numMap) { return [numMap[complement], i]; } numMap[nums[i]] = i; }

1.每个元素遍历了几次?

我们只有一个for循环,这意味着每个数组里面的元素只会遍历一遍

2.每个元素遍历经历了什么

存入哈希表之前

1.被用作计算和自己组合起来符合题意的元素的值

js
代码解读
复制代码
const complement = target - nums[i];

2.被存储在哈希表中作为键值存储在哈希表中,同时下表作为对应键值的值

js
代码解读
复制代码
numMap[nums[i]] = i;

存入哈希表之后

3.作为可被寻找的、其他元素的“另一半”,如果确定是,则输出两元素在原数组的下标

js
代码解读
复制代码
if (complement in numMap) { return [numMap[complement], i]; }

四、下面我们用一个例子来分析最优解的执行过程

js
代码解读
复制代码
nums = [2,7,11,15]; target = 9

具体过程如下(图解)

image.png

image.png

image.png

image.png

五、可执行流程(将代码复杂到编译器运行即可得到动态图解)

html
代码解读
复制代码
html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>两数之和 - 哈希表解法示意图title> <style> body { font-family: 'Arial', sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; background-color: #f5f7fa; } .container { background: white; border-radius: 10px; padding: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } h1 { color: #2c3e50; text-align: center; } .visualization { display: flex; flex-direction: column; gap: 20px; margin-top: 30px; } .array-container { display: flex; justify-content: center; position: relative; height: 100px; } .array-element { width: 60px; height: 60px; background: #3498db; color: white; display: flex; align-items: center; justify-content: center; border-radius: 5px; margin: 0 5px; position: relative; transition: all 0.3s; font-weight: bold; } .array-index { position: absolute; top: -20px; color: #7f8c8d; font-size: 12px; } .hash-table { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; min-height: 120px; background: #ecf0f1; padding: 15px; border-radius: 5px; } .hash-entry { background: #2ecc71; color: white; padding: 8px 12px; border-radius: 5px; display: flex; flex-direction: column; align-items: center; opacity: 0; transform: scale(0.8); transition: all 0.5s; } .hash-entry.visible { opacity: 1; transform: scale(1); } .hash-key { font-weight: bold; border-bottom: 1px solid white; margin-bottom: 3px; padding-bottom: 3px; } .current { box-shadow: 0 0 0 3px #e74c3c; transform: scale(1.1); } .complement { background: #e74c3c; } .found { background: #f39c12; animation: pulse 0.5s 2; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } .explanation { background: #f8f9fa; padding: 15px; border-radius: 5px; margin-top: 20px; border-left: 4px solid #3498db; } .controls { display: flex; justify-content: center; gap: 10px; margin-top: 20px; } button { padding: 8px 15px; background: #3498db; color: white; border: none; border-radius: 5px; cursor: pointer; transition: background 0.3s; } button:hover { background: #2980b9; } style> head> <body> <div class="container"> <h1>两数之和 - 哈希表解法示意图h1> <div class="visualization"> <div class="array-container"> div> <div class="hash-table"> div> div> <div class="explanation"> <p><strong>当前步骤说明:strong> <span id="step-explanation">初始化数组和哈希表span>p> <p><strong>算法原理:strong> 遍历数组,对于每个元素计算 complement = target - nums[i],检查 complement 是否存在于哈希表中。p> div> <div class="controls"> <button id="prev-btn">上一步button> <button id="next-btn">下一步button> <button id="reset-btn">重置button> div> div> <script> // 示例数据 const nums = [2, 7, 11, 15]; const target = 9; let currentStep = 0; let hashMap = {}; // 初始化可视化 function initVisualization() { const arrayContainer = document.querySelector('.array-container'); arrayContainer.innerHTML = ''; // 创建数组元素 nums.forEach((num, index) => { const element = document.createElement('div'); element.className = 'array-element'; element.textContent = num; element.id = `num-${index}`; const indexLabel = document.createElement('div'); indexLabel.className = 'array-index'; indexLabel.textContent = index; element.appendChild(indexLabel); arrayContainer.appendChild(element); }); updateHashTable(); updateExplanation(); } // 更新哈希表显示 function updateHashTable() { const hashTable = document.querySelector('.hash-table'); hashTable.innerHTML = ''; for (const [key, value] of Object.entries(hashMap)) { const entry = document.createElement('div'); entry.className = 'hash-entry visible'; entry.innerHTML = `
${key}
→ ${value}
`; hashTable.appendChild(entry); } } // 更新步骤说明 function updateExplanation() { const explanation = document.getElementById('step-explanation'); const currentElement = document.getElementById(`num-${currentStep}`); const elements = document.querySelectorAll('.array-element'); // 重置所有元素样式 elements.forEach(el => { el.classList.remove('current', 'complement', 'found'); }); switch(currentStep) { case 0: explanation.textContent = "开始遍历数组,当前元素 nums[0] = 2"; currentElement.classList.add('current'); break; case 1: explanation.textContent = "计算 complement = 9 - 2 = 7,7 不在哈希表中,将 2 存入哈希表"; currentElement.classList.add('current'); break; case 2: explanation.textContent = "移动到 nums[1] = 7,计算 complement = 9 - 7 = 2"; currentElement.classList.add('current'); document.getElementById('num-0').classList.add('complement'); break; case 3: explanation.textContent = "发现 2 在哈希表中(索引 0),找到解 [0, 1]!"; currentElement.classList.add('current'); document.getElementById('num-0').classList.add('found'); currentElement.classList.add('found'); break; default: explanation.textContent = "遍历完成"; } } // 下一步 function nextStep() { if (currentStep >= 4) return; switch(currentStep) { case 0: // 准备处理第一个元素 break; case 1: // 处理 nums[0] = 2 hashMap[nums[0]] = 0; break; case 2: // 处理 nums[1] = 7 const complement = target - nums[1]; if (complement in hashMap) { // 找到解的情况 } break; case 3: // 完成 break; } currentStep++; updateHashTable(); updateExplanation(); } // 上一步 function prevStep() { if (currentStep <= 0) return; currentStep--; // 回退哈希表状态 if (currentStep < 1) { hashMap = {}; } else if (currentStep < 2) { hashMap = { [nums[0]]: 0 }; } updateHashTable(); updateExplanation(); } // 重置 function reset() { currentStep = 0; hashMap = {}; initVisualization(); } // 事件监听 document.getElementById('next-btn').addEventListener('click', nextStep); document.getElementById('prev-btn').addEventListener('click', prevStep); document.getElementById('reset-btn').addEventListener('click', reset); // 初始化 initVisualization(); script> body> html>

六、结语

再见!

注:本文转载自juejin.cn的天天扭码的文章"https://juejin.cn/post/7493840646949797940"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

104
前端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top