最近面试前端岗位时,我用了一道经典算法题测试候选人:
// 非空整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现一次的元素
const nums = [9, 4, 5, 9, 1, 1, 5, 68, 4]; // 应输出 68
结果令人震惊——5年经验的老前端卡壳了!7年经验的开始冒汗!10年大佬直接放弃! 甚至有候选人反问:"工作中根本用不到这个,考这有意义吗?"
一、为什么这道题值得考察?
-
基础能力检验:考察对数据操作、循环、位运算的理解
-
问题拆解能力:能否将问题转化为程序逻辑
-
优化意识:能否想到时间复杂度O(n)、空间复杂度O(1)的最优解
二、那些让我眼前一黑的回答实录
-
"我调个lodash..."
(面试禁用第三方库后陷入沉默) -
暴力双循环派:
-
function findSingle(arr) { for (let i = 0; i < arr.length; i++) { let found = false; for (let j = 0; j < arr.length; j++) { if (i !== j && arr[i] === arr[j]) found = true; } if (!found) return arr[i]; } }
(时间复杂度O(n²),空间复杂度O(1) - 勉强算对但效率过低)
Map统计法(稍好但未达最优):
function findSingle(nums) {
const map = new Map();
nums.forEach(n => map.set(n, (map.get(n) || 0) + 1));
for (let [num, count] of map) {
if (count === 1) return num;
}
}
(时间复杂度O(n),但空间复杂度O(n))
三、优雅解法:位运算才是正解
核心思路:利用异或运算的特性
const findSingle = nums => nums.reduce((a, b) => a ^ b);
原理解析:
-
a ^ a = 0(相同数字异或归零) -
a ^ 0 = a(任何数与0异或不变) -
异或满足交换律:
a ^ b ^ a = (a ^ a) ^ b = 0 ^ b = b
逐步推演:
初始值: 0
0 ^ 9 = 9
9 ^ 4 = 13
13 ^ 5 = 8
8 ^ 9 = 1
1 ^ 1 = 0
0 ^ 5 = 5
5 ^ 68 = 73
73 ^ 4 = 68 ✅
四、为什么资深前端会翻车?
-
框架依赖症:过度依赖Vue/React生态,原生JS能力退化
-
算法恐惧症:认为"前端不需要算法"
-
思维固化:工作中习惯调用现成方案,缺乏底层思考
-
知识盲区:不熟悉位运算在实际场景的应用
五、给前端工程师的建议
-
夯实基础:《数据结构与算法》永远不过时
-
理解计算机原理:位运算在压缩、加密等领域广泛应用
-
刻意练习:每周刷2道经典算法题(LeetCode Easy级别足矣)
-
读源码:React/Vue等框架大量使用位运算优化性能
面试的本质不是刁难,而是验证解决问题的能力。这道题反映的不仅是技术缺口,更是面对未知问题时拆解思路的缺失。前端工程师的战场早已不局限于页面布局,性能优化、复杂状态管理、框架开发等场景都需要扎实的算法基础。别让"资深"二字成为技术进步的枷锁!