一维数组去重应避免嵌套循环和重复查找,采用哈希表(Map/对象/布尔数组)单次遍历标记已见元素,时间复杂度从O(n²)降至O(n);保序且ID范围小时用布尔数组最优,字符串或大数用Map,慎用原地splice。

保留顺序 + 避免嵌套查找
如果必须保持元素首次出现的顺序(如签到ID、用户操作日志),就不能直接用 Set 后转回数组——虽然快,但顺序不确定(尤其在旧版 JS 或某些语言中)。更稳妥的做法是:用一个哈希结构(如对象、Map 或布尔数组)**只记录是否见过**,主循环只走一遍。
- 遍历原数组一次,对每个元素检查是否已存在
- 若未存在,加入结果数组,并在哈希表中标记为
true - 时间复杂度从 O(n²) 降到 O(n),空间换时间
避免在循环里反复调用高开销方法
arr.includes(x)、arr.indexOf(x) === -1、newArr.indexOf(item) === index 这类写法,每次都在新数组里从头搜一遍——数组越长,后面每次查找越慢。例如 100 个元素,最后几个元素要各查 90+ 次,总操作量接近 5000 次。
- 换成
seen.has(item)(Map)或seen[item] === true(对象/布尔数组),查找是 O(1) - 对整数 ID(如题中 ≤100 的正整数),甚至可用长度为 101 的布尔数组
bool[101],下标即值,极致轻量
原地处理 or 新建数组?看场景
有些场景要求“原数组修改”(比如嵌入式或内存敏感环境),此时可考虑双指针:先排序(O(n log n)),再用快慢指针跳过相邻重复项(O(n))。但注意——这会破坏原始顺序,且排序本身有开销。
- 若允许改序、数据量大、内存紧张 → 排序 + 双指针更省空间
- 若必须保序、ID 范围小、实时性高 → 布尔标记数组最快最稳
- 若 ID 是字符串或负数/大数 → 用 Map 或 Set 辅助判断
警惕循环中的副作用操作
像 arr.splice(j, 1); j--; 这种边遍历边删的方式,逻辑易错、性能差(数组内部要批量移动后续元素)。尤其在 C 或 Java 中,手动管理数组长度极易越界或漏判。
- 优先选择“构建新数组”,而非“原地删减”
- 真要原地处理,建议先标记待删位置,最后统一收缩,或用两阶段:收集索引 → 反向删除

















