JavaScript数组最高频元素查找:已有解法,求更优雅实现
找出数组中出现次数最多且最先达到最高次数元素的优雅实现
需求说明
- 核心需求:找出数组中出现次数最多的元素;若多个元素出现次数相同,选择最先达到该最高次数的元素
- 输入示例:
['A', 'B', 'C', 'A', 'D', 'B', 'B', 'A', 'D'] - 预期输出:
'B'
原实现分析
你提供的代码逻辑可行,但存在优化空间:
- 两次
reduce加上多次lastIndexOf调用,时间复杂度为O(n²),数组规模较大时效率偏低 - 通过
lastIndexOf间接判断"最先达到最高次数"的逻辑不够直观,易造成理解困惑
更优雅的实现方案
以下是两种高效、直观的实现方式:
方案一:单次for循环实现(推荐,可读性最高)
const findWinner = (arr) => { const countMap = new Map(); let maxCount = 0; let winner = ''; for (const item of arr) { // 更新当前元素的计数 const currentCount = (countMap.get(item) || 0) + 1; countMap.set(item, currentCount); // 仅当当前计数超过最大值时更新结果,保证先达到最高次数的元素被保留 if (currentCount > maxCount) { maxCount = currentCount; winner = item; } } return winner; }; // 测试 const input = ['A', 'B', 'C', 'A', 'D', 'B', 'B', 'A', 'D']; console.log(findWinner(input)); // 输出 'B'
优点:
- 单次遍历完成所有操作,时间复杂度O(n),效率最优
- 逻辑直白:遍历中实时维护元素计数,仅当当前元素计数超过现有最大值时才替换结果,天然保证"最先达到最高次数"的元素被保留(后续元素计数追平时不会替换已有结果)
- 使用
Map而非普通对象,对数组元素类型兼容性更好(支持数字、Symbol等非字符串类型)
方案二:紧凑的reduce写法
如果偏好函数式风格,可用reduce整合状态,同样是单次遍历:
const findWinner = (arr) => { return arr.reduce((state, item) => { const currentCount = (state.countMap.get(item) || 0) + 1; state.countMap.set(item, currentCount); return { countMap: state.countMap, maxCount: currentCount > state.maxCount ? currentCount : state.maxCount, winner: currentCount > state.maxCount ? item : state.winner }; }, { countMap: new Map(), maxCount: 0, winner: '' }).winner; }; // 测试 const input = ['A', 'B', 'C', 'A', 'D', 'B', 'B', 'A', 'D']; console.log(findWinner(input)); // 输出 'B'
优点:
- 保持函数式编程风格,代码紧凑
- 同样是O(n)时间复杂度,效率与for循环一致
内容的提问来源于stack exchange,提问作者Deepika Deepi
相关产品推荐
相关产品推荐

