基础不牢,AI 无用;思维到位,一行胜千行
前几篇文章,我一直在「往上走」。
从序章的 Vibe Coding + 提示词工程,到 Claude Code 工程掌控,再到大厂级模块化系统、位运算刷题实战,一路冲到 FDE 时代核心力,每一篇都在拉高抽象层次,每一篇都在拓展 AI 开发的能力边界。 然后,我老老实实坐下来,写了一道数组去重题。
我才突然意识到,自己一路追着「高级玩法」跑,却差点忘了最底层的基本功。这道题看似简单,六种解法背后,藏着的是我之前所有学习的底层逻辑 —— 从暴力解法的基础,到数据结构的优化,再到 API 的优雅封装,和我一路学过来的路,一模一样。 往上走得再高,也要往下扎得深。
前端面试必问:数组去重,从原理到6种最优解(面试官最爱)
这篇文章我们来彻底搞定前端面试超高频考点:数组去重。 不管是大厂面试、中小厂笔试,还是日常业务开发,数组去重都是绕不开的基础题。 很多人以为一句[...new Set(arr)]就完事了,但面试官真正想考察的,远不止这些。
一、先搞懂:面试官到底在考什么?
数组去重这道题,表面考功能,实际考这些:
- 常见业务逻辑是否熟练 - 会不会手写基础工具函数
- 能不能给出多种解法
- 是否熟悉数组 API -
- 能不能说出每种方法优缺点-
- 是否理解底层数据结构-
- 代码是否健壮、可读、可维护
能写出去重 = 60分
能讲清原理 = 90分
能对比优劣 + 选择合适方案 = 100分
二、从 0 到 1:先搭好函数的架子
2.1 写注释 —— 不仅仅是给程序员看的
很多同学一上来就写逻辑,忽略了注释。但在面试中,注释体现了你的协作意识和可维护性思维。
/** * @func unique 数组去重 * @param{Array}arr - 输入数组 * @returns{Array}- 去重后的数组 * @author xz * @date2026-05-27 */functionunique(arr){// 实现...}2.2 参数校验 —— 永远不要相信用户的输入
面试官会故意传null、undefined、字符串甚至对象进来,看你有没有防御意识,函数健壮性非常重要,面试官特别看重这一点。
functionunique(arr){// 参数校验 不是数组,返回空数组 if(!Array.isArray(arr)){console.log('type error')return[];}// 正式去重逻辑...7种实战解法,从基础到高效
第一层:双重循环——暴力美学的价值
for(let i=0;i<arr.length;i++){2for(let j=i +1;j<arr.length;j++){3if(arr[i]===arr[j]){4arr.splice(j,1)5j--6}7}优点:好理解 缺点:O (n²) 效率低
解法 2:indexOf 去重
functionunique(arr){if(!Array.isArray(arr))return[];letres=[];for(let i=0;i<arr.length;i++){if(res.indexOf(arr[i])===-1){res.push(arr[i]);}}returnres;}开始用 API 了:
解法 3:排序后相邻去重
js
functionunique(arr){if(!Array.isArray(arr))return[];letres=[];letsortArr=[...arr].sort();for(let i=0;i<sortArr.length;i++){if(sortArr[i]!==sortArr[i -1]){res.push(sortArr[i]);}}returnres;}优点:快 O (n log n)缺点:破坏原数组顺序
解法 4:对象哈希表去重(空间换时间)
js
functionunique(arr){if(!Array.isArray(arr))return[];letobj={};letres=[];for(let item of arr){letkey=typeof item + item;if(!obj[key]){obj[key]=true;res.push(item);}}returnres;}优点:O (n) 效率极高数据结构思想:空间换时间
解法5:Map—— 完美哈希表
functionuniqueByMap(arr){if(!Array.isArray(arr))return[];const map=new Map();const res=[];for(let item of arr){if(!map.has(item)){map.set(item,true);res.push(item);}}returnres;}保留顺序,O(n) 时间,O(n) 空间
这是面试官非常认可的生产环境实现
解法 6:Set 去重(最优雅)
const unique=arr=>[...new Set(arr)];优点:代码最少、效率高、稳定缺点:需要 ES6 支持(现代项目无压力) 表格
| 方法 | 复杂度 | 优点 | 缺点 |
|---|---|---|---|
| 双循环 | O(n²) | 好理解 | 效率低 |
| filter | O(n²) | 代码简洁 | 效率低 |
| 排序相邻 | O(n log n) | 快 | 乱序 |
| 哈希 | O(n) | 极快 | 占空间 |
| Set | O(n) | 极快、简洁、稳定 | 推荐 |
1. 基础不牢,AI 也救不了你
AI 时代,很多人觉得:“我不用手写,AI 会写就行。” 但真相是: 你不懂基础,就无法判断 AI 写得对不对、优不优、稳不稳。 你没写过双循环,就不知道 O (n²) 有多慢 你没踩过哈希的坑,就不知道 1 和 ‘1’ 会冲突 你不懂参数校验,就不知道函数为什么会崩 你不懂复杂度,就不知道什么叫 “优化” AI 是执行者,你是决策者。 决策者的能力,来自底层基本功。
2. 向上抽象 & 向下扎根,是同一件事
我们学 Prompt、学 Agent、学模块化、学工程、学 FDE, 看起来是 “往上走”, 但最终会发现: 高级能力的底层,还是基础题里那套思维。 模块化:拆分职责、清晰语义 数据结构:选对工具、空间换时间 Prompt:精准描述意图 数组去重:从暴力到最优,也是精准描述意图 往上走得再高,也要往下扎得深。 没有底层,上层都是空中楼阁。
3. 好代码 = 更准确地描述 “我要什么”
六种解法一路看下来,你会发现: 代码越少,不一定越厉害; 但越贴近问题本质,一定越高级。
双重循环说:我要比较每一个 indexOf 说:我要查有没有 哈希表说:我要标记存在过 Set 说:我要一个不重复的集合编程的终极,不是写指令,是描述意图。
4. 面试真正要的人:能讲清 “为什么”
会写 Set 只是及格。 能讲出六种方法、复杂度、优缺点、适用场景, 才是面试官想要的:
基础扎实、思路清晰、懂工程、懂取舍、可成长。
一题见功底,一题见思维。
用我朋友的话说:“Be AI Native 的路上,没有"高级"和"基础"的区别。你在一道小题里看到的思维深度,就是你在大项目里能走到的认知高度”
点点关注呀! 下篇见!
