温州建设信息港网站html5网络公司网站模板
2026/4/6 5:58:38 网站建设 项目流程
温州建设信息港网站,html5网络公司网站模板,怎样才能建一个网站,什么是响应式营销型网站建设你不用慌#xff0c;刚开始刷 LeetCode 热题 100 连第一题#xff08;两数之和#xff09;都不会#xff0c;是所有编程新手的常态#xff0c;这不是你能力的问题#xff0c;而是还没掌握「解算法题的基本思路」和「前端视角的解题方法」。我会从最基础的步骤带你拆解这道…你不用慌刚开始刷 LeetCode 热题 100 连第一题两数之和都不会是所有编程新手的常态这不是你能力的问题而是还没掌握「解算法题的基本思路」和「前端视角的解题方法」。我会从最基础的步骤带你拆解这道题帮你建立「从 0 到 1 解算法题」的思维而不是直接给答案。第一步先读懂「两数之和」的题目LeetCode 1. 两数之和先把题目拆成「人话」明确输入、输出、核心要求输入一个整数数组nums 一个目标值target输出数组中两个不同位置的数的下标这两个数相加等于target要求每个输入只有一个答案同一个元素不能用两次。示例输入nums [2,7,11,15], target 9→ 输出[0,1]因为 279。第二步从「最笨的方法」开始新手先落地再优化新手不要一上来就想「最优解」先写「能跑通的代码」再谈优化。这道题最容易理解的是「暴力枚举法」两层循环思路遍历数组中的每一个数nums[i]对于每个nums[i]再遍历它后面的所有数nums[j]j i避免重复检查nums[i] nums[j]是否等于target如果是直接返回[i,j]。前端JS实现代码带详细注释javascript运行/** * param {number[]} nums 输入的整数数组 * param {number} target 目标和 * return {number[]} 满足条件的两个数的下标 */ var twoSum function(nums, target) { // 第一层循环遍历每个元素i是第一个数的下标 for (let i 0; i nums.length; i) { // 第二层循环遍历i后面的元素j是第二个数的下标避免重复用同一个元素 for (let j i 1; j nums.length; j) { // 核心判断两数之和等于目标值 if (nums[i] nums[j] target) { // 找到答案直接返回下标数组 return [i, j]; } } } // 题目说必有解这里只是兜底实际不会执行 return []; }; // 测试用例新手一定要写测试验证自己的代码 console.log(twoSum([2,7,11,15], 9)); // 输出 [0,1] console.log(twoSum([3,2,4], 6)); // 输出 [1,2] console.log(twoSum([3,3], 6)); // 输出 [0,1]代码解释新手逐行看for (let i 0; i nums.length; i)遍历数组的每一个元素i是第一个数的下标for (let j i 1; j nums.length; j)j从i1开始确保不会重复使用同一个元素比如不会出现i0,j0的情况nums[i] nums[j] target判断两数之和是否等于目标值满足则返回下标测试用例覆盖了「普通情况」「非相邻元素」「重复值」验证代码的鲁棒性。复杂度分析大厂面试必说时间复杂度O(n2)n 是数组长度因为两层循环最坏情况要遍历 n∗(n−1)/2 次空间复杂度O(1)只用到了几个变量没有额外开辟大空间。第三步优化解法前端高频考的「哈希表法」暴力法虽然好理解但效率低O(n2)大厂面试会追问「能不能优化」这时候要讲「哈希表Map」的解法时间复杂度 O(n)。思路新手记这个「核心逻辑」用一个Map来「存已经遍历过的数 它的下标」空间换时间遍历数组时对当前数nums[i]计算「需要找的补数」complement target - nums[i]检查Map里有没有这个补数如果有说明之前遍历过这个补数直接返回「补数的下标」和「当前下标 i」如果没有把当前数nums[i]和下标i存入Map继续遍历。JS 实现代码带注释javascript运行var twoSum function(nums, target) { // 1. 创建一个Map用来存「已遍历的数: 下标」 const map new Map(); // 2. 遍历数组i是当前下标num是当前数 for (let i 0; i nums.length; i) { const num nums[i]; // 3. 计算需要找的补数 const complement target - num; // 4. 检查Map里有没有这个补数 if (map.has(complement)) { // 有则返回补数的下标 当前下标 return [map.get(complement), i]; } // 5. 没有则把当前数和下标存入Map map.set(num, i); } // 兜底返回题目保证有解 return []; }; // 测试用例 console.log(twoSum([2,7,11,15], 9)); // [0,1] console.log(twoSum([3,2,4], 6)); // [1,2] console.log(twoSum([3,3], 6)); // [0,1]核心解释新手重点理解Map的作用把「找补数」的操作从「遍历数组O (n)」变成「查 MapO (1)」为什么不会重复因为先查补数再存当前数所以当前数不会和自己匹配比如nums[3,3]遍历第一个 3 时Map 为空存入 Map遍历第二个 3 时补数是 3Map 里有第一个 3 的下标 0直接返回 [0,1]复杂度时间 O(n)只遍历一次空间 O(n)最坏情况存 n-1 个数。第四步新手刷这道题的「正确姿势」比会写更重要先抄再理解如果完全不会先把暴力法的代码抄一遍逐行改测试用例比如把 nums 改成 [1,2,3]target 改成 5看输出是否正确理解每一行的作用自己写一遍关掉答案自己写暴力法写完后用测试用例验证遇到 bug比如 j 从 0 开始导致重复自己排查思考优化点问自己「为什么暴力法慢」「哪里可以省时间」再尝试写哈希表法复盘总结这道题的核心是「空间换时间」哈希表是前端解「数组 / 字符串匹配」的高频工具记住这个思路比如后续刷「字母异位词」「两数之和变种题」都能用。第五步给你的「新手刷题小建议」针对热题 100不要跳题热题 100 是按「基础→进阶」排的第一题是最基础的哈希表应用吃透它再刷下一题比如第二题两数相加是链表题先把数组 / 哈希表的基础打牢每天只刷 1 道新手不用贪多每天把 1 道题的「暴力法 最优解」都搞懂手写 2 遍比一天刷 5 道半懂不懂的题有用记「模板」不记答案这道题的哈希表模板可以记下来javascript运行// 哈希表解题模板数组匹配类 const map new Map(); for (let i 0; i arr.length; i) { const need target - arr[i]; if (map.has(need)) { return [map.get(need), i]; } map.set(arr[i], i); }用前端语言写全程用 JS/TS 写不用纠结 Python/Java 的写法大厂前端面试只看你用前端语言的实现。总结新手不会第一题完全正常核心是先从「暴力法」落地再理解「最优解」不要一开始就追求完美「两数之和」的核心考点是哈希表的空间换时间思想这是前端算法的高频考点必须吃透刷题的关键是「理解 手写 复盘」而不是背答案哪怕一天只搞懂 1 道题也是有效进步。什么是哈希表哈希表Hash Table其实是前端开发中天天都在用的东西只是你可能没意识到它的名字而已。我会用最通俗的比喻 前端实际例子帮你彻底搞懂哈希表以及它在「两数之和」里的作用。第一步先理解「哈希表」的核心概念用生活例子比喻哈希表的本质是「键值对Key-Value存储结构」核心作用是通过「键Key」快速找到「值Value」就像我们生活中的「字典」或「通讯录」字典通过「汉字Key」快速查到「释义Value」不用从头翻通讯录通过「名字Key」快速找到「手机号Value」不用一个个找哈希表通过「自定义的键」快速找到「对应的值」时间复杂度接近 O(1)瞬间找到。对比为什么哈希表比「遍历数组」快遍历数组找值比如在[2,7,11,15]里找 7需要从头数第 2 个最坏要找完整个数组O(n)哈希表找值把数组存成{2:0, 7:1, 11:2, 15:3}找 7 的话直接查哈希表[7]一步到位O(1)。第二步前端里的「哈希表」就是这些东西在 JavaScript 中我们不用自己实现哈希表直接用现成的「对象Object」或「Map」就行 —— 这两个都是哈希表的具体实现前端哈希表载体特点常用场景Object对象键只能是字符串 / 数字 / Symbol简单场景比如存数字、字符串键Map键可以是任意类型数字、对象、函数等有专门的 APIhas/set/get算法题 / 复杂场景推荐用举个前端实际例子先感受用法javascript运行// 1. 用Object模拟哈希表存「数:下标」 const objMap {}; // 存值键是数字2值是下标0 objMap[2] 0; // 取值通过键2瞬间拿到值0 console.log(objMap[2]); // 输出 0 // 检查是否有某个键 console.log(2 in objMap); // 输出 true // 2. 用Map算法题更推荐语义更清晰 const map new Map(); // 存值set(键, 值) map.set(7, 1); // 取值get(键) console.log(map.get(7)); // 输出 1 // 检查是否有某个键has(键) console.log(map.has(7)); // 输出 true // 删除键delete(键) map.delete(7); console.log(map.has(7)); // 输出 false第三步回到「两数之和」理解哈希表的作用我们再回头看「两数之和」的优化解法就能明白哈希表到底在干嘛问题核心痛点暴力法的问题暴力法要两层循环是因为对每个数nums[i]都要「遍历剩下的数」找target - nums[i]补数这个找的过程是 O(n)所以整体是 O(n2)。哈希表的解决思路空间换时间我们把「已经遍历过的数和它的下标」存到哈希表里这样找补数的过程就从「遍历数组」变成「查哈希表」O(1)整体时间复杂度降到 O(n)。用「通讯录」比喻这一过程假设目标和 target 9数组 nums [2,7,11,15]哈希表 你的「通讯录」存的是「数下标」。遍历过程遍历第一个数 2下标 0补数 9 - 2 7查通讯录有没有 7没有把 2 和下标 0 存进通讯录通讯录{2:0}遍历第二个数 7下标 1补数 9 - 7 2查通讯录有 2对应的下标是 0直接返回 [0,1]结束。再看代码就完全懂了javascript运行var twoSum function(nums, target) { // 1. 初始化哈希表空通讯录 const map new Map(); // 2. 遍历数组一个个看数 for (let i 0; i nums.length; i) { const num nums[i]; // 当前数 const complement target - num; // 补数要找的数 // 3. 查哈希表有没有这个补数 if (map.has(complement)) { // 有就返回补数的下标 当前下标 return [map.get(complement), i]; } // 4. 没有就把当前数和下标存进哈希表 map.set(num, i); } return []; };第四步新手必懂的哈希表核心考点前端算法核心优势「查询 / 插入 / 删除」的平均时间复杂度都是 O(1)这是它能优化算法的关键前端算法常见用法计数比如统计数组中每个数出现的次数去重比如数组去重存到 Map/Set 里快速匹配比如两数之和、字母异位词缓存比如存已经计算过的结果避免重复计算和数组的区别操作数组哈希表Map按值找下标O(n)O(1)按下标找值O(1)不支持哈希表没有下标存储结构有序下标无序ES6 的 Map 是有序的但算法题不关注总结哈希表的核心是「键值对存储」能通过键快速找到值O(1)前端用Object或Map实现在「两数之和」中哈希表的作用是「存已遍历的数和下标」把找补数的时间从 O(n) 降到 O(1)实现算法优化哈希表是前端算法的「高频工具」只要遇到「需要快速查找 / 匹配」的场景优先想到它。为什么哈希表比数组快不应该都是从头开始找吗你这个问题问到了哈希表的核心原理上很多新手都会有这个疑问 ——「哈希表看起来也是存了一堆键值对为什么找 7 不用从头遍历」其实关键在于哈希表的「哈希函数」和「存储结构」和数组的遍历完全不是一回事。我用最通俗的方式给你讲明白不用看复杂的公式只理解核心逻辑就行。第一步先推翻「哈希表需要从头找」的误区数组的存储是「连续的内存地址」比如[2,7,11,15]存的时候是按顺序放在内存里下标 0 → 地址 A → 存 2下标 1 → 地址 A1 → 存 7下标 2 → 地址 A2 → 存 11所以找 7 的时候只能从地址 A 开始一个个查直到找到地址 A1这就是「遍历」O (n)。而哈希表比如 JS 的 Object/Map的存储逻辑完全不同它不是按顺序存而是通过「哈希函数」把键比如 7直接转换成一个内存地址存的时候直接放到这个地址查的时候也直接用这个地址取 —— 相当于给每个键分配了一个「专属储物柜」找的时候不用挨个翻直接去对应的柜子拿就行。第二步用「快递柜」比喻哈希表的核心逻辑我们用生活中的「快递柜」来比喻你一下就能懂存快递存键值对你有一个快递键 7值 1快递柜有个「编码规则」哈希函数键的数字 % 10取余就是柜号计算 7 % 10 7 → 直接把快递放进 7 号柜同理2 → 2 号柜11 → 1 号柜15 →5 号柜。取快递查值要找键 7 对应的值不用从 1 号柜翻到 10 号柜直接用编码规则算7%107 → 打开 7 号柜直接拿到快递值 1整个过程只有「计算柜号 开柜」两步和有多少个快递无关 —— 这就是 O (1)常数时间。对比数组的「货架」逻辑数组是「一排货架」找 7 的时候要从第一个货架开始数1 号2→2 号7数到第二个才找到货架越长数的次数越多O (n)。第三步回到 JS 的哈希表Object/Map看实际逻辑JS 里的 Object/Map 底层就是用这个原理实现的细节比快递柜复杂但核心一致当你执行map.set(7, 1)时JS 引擎会用「哈希函数」把键 7 转换成一个哈希值比如一串数字然后把值 1 存在这个哈希值对应的内存位置当你执行map.get(7)时不会遍历所有键而是再次用同一个哈希函数算出 7 的哈希值直接去对应的内存位置取值 —— 不管 Map 里有 10 个还是 1000 个键值对这个过程都是「一次计算 一次取值」时间复杂度就是 O (1)。第四步补充一个小细节哈希冲突你可能会问如果两个键的哈希值一样怎么办比如键 7 和 17按「%10」的规则都对应 7 号柜这叫「哈希冲突」。其实哈希表有解决冲突的办法比如「链表法」7 号柜里放一个小链表先存 7→1再存 17→2查的时候到 7 号柜后只需要遍历这个小链表通常只有 1-2 个元素整体还是接近 O (1)远快于遍历整个数组。用代码验证哈希表查值和数组查值的效率差异我们用 10 万条数据做对比你能直观看到区别javascript运行// 1. 准备数据10万个数字的数组 对应的哈希表 const nums []; const hashMap new Map(); for (let i 0; i 100000; i) { nums.push(i); hashMap.set(i, i); } // 2. 数组找值找99999需要遍历10万次 console.time(数组查找); const index nums.findIndex(item item 99999); console.timeEnd(数组查找); // 耗时约几毫秒随数据量增长 // 3. 哈希表找值找99999一次到位 console.time(哈希表查找); const value hashMap.get(99999); console.timeEnd(哈希表查找); // 耗时约0.01毫秒几乎不随数据量增长运行后你会发现数组查找的耗时会随着数据量增加而明显变长而哈希表几乎不变 —— 这就是 O (n) 和 O (1) 的本质区别。总结哈希表查值不用从头遍历核心是通过「哈希函数」把键直接转换成存储地址查值时直接取对应地址的值数组是「顺序存储 下标访问」按值找下标必须遍历哈希表是「哈希地址存储 键访问」按键找值一步到位「两数之和」用哈希表优化的核心就是把「遍历数组找补数O (n)」换成「哈希表查补数O (1)」从而把整体时间复杂度从 O (n²) 降到 O (n)。把哈希函数、哈希冲突这两个哈希表的核心细节用「快递柜」的比喻继续讲透还是保持通俗不绕公式同时补充前端算法题里用得到的知识点面试被追问也能答上来一、哈希函数哈希表的「快递柜编码规则」哈希函数Hash Function是哈希表的核心作用就是把任意类型的「键Key」转换成一个固定长度的「哈希值Hash Code」这个哈希值就是键在哈希表中的「存储地址标识」。1. 核心要求算法题 / 面试只记这 3 点确定性同一个键永远算出同一个哈希值比如键 7每次算都是 7不能这次 7 下次 8高效性计算速度要快不能比遍历数组还慢均匀性计算出的哈希值要均匀分布尽量避免多个键算出同一个值减少冲突。2. 举个前端能懂的「简易哈希函数」例子算法题里我们接触的键大多是数字 / 字符串用简单的算法就能做哈希函数比如键是数字直接取余key % 数组长度比如键 7、17、27对 10 取余得到 7、7、7这就是后面要讲的冲突键是字符串比如键abc可以把每个字符的 ASCII 码相加再取余a(97)b(98)c(99)294对 10 取余得 4哈希值就是 4。3. JS 里的哈希函数不用自己实现了解即可我们写算法题用的Map/ObjectJS 引擎已经帮我们实现了高效的哈希函数对数字 / 字符串 / Symbol直接生成唯一哈希值对对象 / 数组根据内存地址生成哈希值所以两个内容相同的空对象{} ! {}哈希值不同Map 里会当成两个键。✅前端算法题小技巧如果需要用对象当 Map 的键先把对象转成字符串比如JSON.stringify(obj)避免因内存地址导致的哈希值不同。二、哈希冲突多个快递「撞柜」了怎么办不管哈希函数设计得多好必然会出现「不同的键算出同一个哈希值」的情况这就是哈希冲突—— 比如按key%10的规则键 7 和 17 都算出 7都要放 7 号快递柜这就是撞柜了。1. 为什么冲突不可避免核心是「鸽巢原理」比如有 10 个快递柜哈希值范围 0-9但要存 11 个快递必然有至少一个柜子要放 2 个快递哈希表的哈希值范围是固定的而键的数量是无限的冲突是必然的。2. 哈希表解决冲突的两种核心方法面试高频记名字 思路哈希表的底层实现主要用这两种方法解决冲突前端算法题不用实现但要能说清思路大厂面试偶尔会追问「哈希表怎么解决冲突」方法 1链地址法拉链法—— 快递柜里「加层板」这是最常用的方法也是 JSMap/Object底层用的方法思路超简单把哈希表的每个存储位置快递柜变成一个链表 / 数组当多个键哈希值相同时就把这些键值对依次存到同一个位置的链表中相当于快递柜里加层板一层放一个快递。用快递柜比喻链地址法规则key%10柜号 0-9存键 7值 17 号柜空直接放进去7 号柜→[7:1]存键 17值 2哈希值也是 77 号柜加层板7 号柜→[7:1, 17:2]存键 27值 3继续加层板7 号柜→[7:1, 17:2, 27:3]查值找 17 时先算哈希值 7→打开 7 号柜→遍历柜内的小链表找到 17 对应的值 2。✅ 关键链地址法的查询效率依然接近 O (1)因为哈希函数的均匀性每个柜子里的链表都很短通常 1-2 个元素遍历的代价可以忽略。方法 2开放寻址法 —— 撞柜了就「找隔壁空柜子」思路当某个位置被占了就按一定规则依次查找下一个空的存储位置把键值对存进去常见的规则是「线性探测」往后找 1 个再找 1 个。用快递柜比喻开放寻址法规则key%10柜号 0-9存键 7值 17 号柜空直接放7 号柜→7:1存键 17值 27 号柜被占找隔壁 8 号柜空的存 8 号柜→17:2存键 27值 37 号、8 号都被占找 9 号柜空的存 9 号柜→27:3查值找 17 时先算 7 号柜→没有→找 8 号柜→找到 17:2。❌ 缺点如果哈希表存得很满会出现「连续占柜」的情况查询时要找很多次效率会降到 O (n)所以开放寻址法的哈希表不能存太满。三、前端算法题里哈希表的这些细节不用纠结讲完哈希函数和冲突你可能会担心「刷题时要不要考虑这些」答案是完全不用因为JS 的Map/Object已经帮我们实现了「高效哈希函数 链地址法解决冲突」我们只用调用set/get/has就行不用关心底层算法题里考察的是哈希表的使用思路空间换时间不是底层实现面试官也不会让前端手写哈希表我们刷的题中哈希表的查询效率都可以直接按O(1)算不用考虑冲突的遍历代价。四、哈希表核心知识点总结面试答题版如果面试被追问「哈希表的原理」把这几句按顺序说简洁又到位完全够前端的考察要求哈希表的核心是键值对存储通过哈希函数把键转换成哈希值作为存储地址实现按键的 O (1) 查询由于鸽巢原理哈希冲突不可避免常用链地址法拉链法解决将冲突的键值对存到同一个地址的链表中前端中用Object/Map实现哈希表Map 支持任意类型的键解决了 Object 键只能是字符串 / 数字的问题算法题中更推荐用 Map。最后再回到「两数之和」串一遍完整逻辑现在你懂了底层再看这道题的哈希表解法就是完整的逻辑链了初始化 Map空的哈希表有自己的哈希函数和冲突解决机制遍历数 7计算补数 2→调用map.has(2)→Map 内部用哈希函数算出 2 的哈希值→找到对应地址→地址为空返回 false调用map.set(7,1)→Map 用哈希函数算出 7 的哈希值→存到对应地址遍历数 2计算补数 7→调用map.has(7)→算出 7 的哈希值→找到对应地址→地址里有 7:1返回 true→调用map.get(7)拿到 1返回 [1,0]。到这里哈希表的核心原理就全懂了从「怎么用」到「为什么快」再到「底层细节」完全覆盖前端算法题和面试的要求

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询