javascript数组无法真正原地去重,但可用双指针+splice实现逻辑原地去重:慢指针记唯一位置,快指针找新元素,遇重复则splice删除并i--回退,时间复杂度o(n²)。

JavaScript 数组去重无法真正“原地修改”(即不创建新数组、不改变内存地址),但可以通过修改原数组的 length 和 索引元素 实现逻辑上的“原地去重”——即复用原数组内存空间,不返回新数组,且原数组变量指向不变。
用双指针+splice实现逻辑原地去重
这是最贴近“原地”语义的做法:遍历数组,用慢指针记录唯一元素位置,快指针找新元素;一旦发现重复,用 splice 删除当前项,并回退快指针以避免跳过下一项。
- 注意:每次
splice(i, 1)会改变后续索引,所以循环中需i-- - 时间复杂度 O(n²),适合小数组或对内存敏感场景
function uniqueInPlace(arr) {
for (let i = 0; i
<h3>用 Set + 赋值覆盖 + length 截断(推荐)</h3>
<p>利用 <code>Set</code> 去重后转为数组,再逐个赋值回原数组前部,最后截断多余长度。不创建新数组变量,原引用不变,内存复用程度高。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java"><img
src="https://img.php.cn/upload/skill/000/000/081/178955835420587.jpg" alt="Alibabacloud Sdk Client Initialization For Java" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java" class="overflowclass">Alibabacloud Sdk Client Initialization For Java</a>
<p class="overflowclass">在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。</p>
</div>
<a rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 只修改原数组的已有索引和
length属性,不调用push/pop等新增/删减操作 - 时间复杂度 O(n),性能好,兼容性佳(ES6+)
function uniqueInPlace(arr) {
const seen = new Set();
let writeIndex = 0;
for (let i = 0; i
<h3>注意事项与边界情况</h3>
<p>所谓“原地”,本质是保持 <code>arr === originalArray</code> 为 <code>true</code>,但以下情况需留意:</p>
-
对象/数组等引用类型去重:需用
JSON.stringify或自定义比较,否则===永远为false -
NaN 和 -0:
Set中NaN只存一个,-0 === +0为true,符合常规预期 -
稀疏数组:含空槽(empty slot)时,
for...of或forEach会跳过,建议用普通for循环配合in或hasOwnProperty
为什么不直接用 filter + 赋值?
arr = [...new Set(arr)] 或 arr = arr.filter(...) 看似简洁,但会令 arr 指向一个全新数组对象,原引用丢失——这不符合“原地”要求。即使在函数内赋值,外部变量也不会改变(除非传入的是对象属性,如 obj.arr)。
真正的原地去重,核心就两点:不改引用、只动 arr[i] 和 arr.length。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










