如何实现数组从头部去重并返回指定数量结果,无需处理完整数组
方案说明
核心结论:由于需要确认每个元素最后一次出现的位置,必须至少遍历一次完整数组,无法完全跳过全量处理,但可以在收集结果的阶段提前终止,避免不必要的二次遍历开销。
以下是两种常用实现:
方案1:两次遍历,第二次遍历提前终止
先遍历一次全量数组记录每个元素最后一次出现的索引,第二次正序遍历数组,仅收集索引等于最后出现索引的元素,收集满limit条即可直接终止遍历,不需要处理剩余元素。
const limit = 3; const arr = [1,2,2,5,1,6]; // 第一步:遍历完整数组记录每个元素最后一次出现的索引 const lastOccur = new Map(); for (let i = 0; i < arr.length; i++) { lastOccur.set(arr[i], i); } // 第二步:正序收集,满limit立即停止 const res = []; for (let i = 0; i < arr.length && res.length < limit; i++) { const item = arr[i]; if (lastOccur.get(item) === i) { res.push(item); } } console.log(res); // 输出 [2,5,1]
适用场景:limit数值较小的场景,第二次遍历通常不需要走完整个数组就能收集满结果,综合开销更低。
方案2:单次倒序遍历
从数组末尾倒序遍历,用Set记录已经出现过的元素,遇到未出现的元素就存入临时数组,遍历完成后反转临时数组取前limit条即可。
const limit = 3; const arr = [1,2,2,5,1,6]; const seen = new Set(); const temp = []; // 单次倒序遍历完整数组 for (let i = arr.length - 1; i >= 0; i--) { const item = arr[i]; if (!seen.has(item)) { seen.add(item); temp.push(item); } } // 反转后截取前limit条 const res = temp.reverse().slice(0, limit); console.log(res); // 输出 [2,5,1]
适用场景:limit数值接近去重后数组总长度的场景,单次遍历的总成本低于两次遍历。
内容的提问来源于stack exchange,提问作者Himanshu Teotia
相关产品推荐
相关产品推荐

