AI 文章摘要
正在生成文章摘要,请稍候...
这是一道JS面试题,要求在不修改原数组、不使用额外空间的情况下寻找数组中的重复数。题目条件为数组长度n+1,数字范围1到n。解法采用链表思想,使用快慢指针找到环的相遇点,然后通过头指针和慢指针同步移动找到环的入口,即重复元素。具体步骤包括:快慢指针追逐直到相遇,然后从起点和相遇点同时出发以相同速度移动,最终在环入口相遇得到重复数。代码演示了这一过程,并通过详细注释解释了指针移动和环形成的原理。
这几天遇到一个很有意思的面试题,我们一起看看
JS面试题寻找重复数
n+1个整数数字范围:
1到n
绝对不能修改原数组(禁用排序等操作)
禁用常量级额外空间O(1)(常规哈希表操作堵死)
其实很简单,我们可以想到使用链表方式
-
把数组当链表
-
快慢指针追逐,找到环里的相遇点
只要有环,快指针一定能追上慢指针
就像两个人在操场跑步,快的一定会套圈慢的
-
头指针 + 慢指针同步走 —— 找到环的入口
答案:
let slow = 0, fast = 0;
const nums = [3, 1, 4, 2, 6, 7, 3];
console.log("遍历数组", nums);
console.log("======================================");
while (true) {
console.log("【本轮开始】slow 位置:" + slow + ",值:" + nums[slow]);
console.log("【本轮开始】fast 位置:" + fast + ",值:" + nums[fast]);
// 慢指针走一步(先输出,再移动)
slow = nums[slow];
console.log("慢指针移动 → 新位置:" + slow + ",新值:" + nums[slow]);
// 快指针走两步
let step1 = nums[fast];
fast = nums[step1];
console.log("快指针移动 → 新位置:" + fast + ",新值:" + nums[fast]);
console.log("--------------------------------------");
if (slow === fast) {
console.log("✅ 快慢指针相遇!位置:" + slow + ",值:" + nums[slow]);
break;
}
}
console.log("======================================");
let head = 0;
console.log("开始从头查找重复元素...");
while (head !== slow) {
console.log("【本轮开始】head 位置:" + head + ",值:" + nums[head]);
console.log("【本轮开始】slow 位置:" + slow + ",值:" + nums[slow]);
// 头指针走一步
head = nums[head];
console.log("头指针移动 → 新位置:" + head + ",新值:" + nums[head]);
// 慢指针走一步
slow = nums[slow];
console.log("慢指针移动 → 新位置:" + slow + ",新值:" + nums[slow]);
console.log("--------------------------------------");
}
console.log("🎉 最终重复元素:" + slow);
输出结果:
遍历数组 [
3, 1, 4, 2,
6, 7, 3
]
======================================
【本轮开始】slow 位置:0,值:3
【本轮开始】fast 位置:0,值:3
慢指针移动 → 新位置:3,新值:2
快指针移动 → 新位置:2,新值:4
--------------------------------------
【本轮开始】slow 位置:3,值:2
【本轮开始】fast 位置:2,值:4
慢指针移动 → 新位置:2,新值:4
快指针移动 → 新位置:6,新值:3
--------------------------------------
【本轮开始】slow 位置:2,值:4
【本轮开始】fast 位置:6,值:3
慢指针移动 → 新位置:4,新值:6
快指针移动 → 新位置:2,新值:4
--------------------------------------
【本轮开始】slow 位置:4,值:6
【本轮开始】fast 位置:2,值:4
慢指针移动 → 新位置:6,新值:3
快指针移动 → 新位置:6,新值:3
--------------------------------------
✅ 快慢指针相遇!位置:6,值:3
======================================
开始从头查找重复元素...
【本轮开始】head 位置:0,值:3
【本轮开始】slow 位置:6,值:3
头指针移动 → 新位置:3,新值:2
慢指针移动 → 新位置:3,新值:2
--------------------------------------
🎉 最终重复元素:3
指针位置:
| 值 | 3 | 1 | 4 | 2 | 6 | 7 | 3 |
|---|---|---|---|---|---|---|---|
| 指针 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
slow指针:
| 指针位置 | 对应值 |
|---|---|
| 0 | 3 |
| 3 | 2 |
| 2 | 4 |
| 4 | 6 |
| 6 | 3 |
因为指针6指向值3,使用指针3最终再次指向指针6,因此形成环
fast指针:
注意, fast 指针每次走两步是通过两次取值实现的
| 指针位置 | 对应值 |
|---|---|
| 2 | 4 |
| 6 | 3 |
| 2 | 4 |
| 6 | 3 |
| 2 | 4 |
| 6 | 3 |
slow指针与fast指针相等,while循环跳出,循环结束
查找重复元素
新定义头指针,让头指针从0走一遍
slow指针,也跟着头指针走一遍(注意没有赋值为0,此时slow值为6)
初始指针状态:
| 指针类型 | 指针位置 | 值 |
|---|---|---|
| 头指针0 | 0 | 3 |
| slow指针 | 6 | 3 |
循环指针过程:
| 指针类型 | 指针位置 | 值 |
|---|---|---|
| 头指针 | 3 | 2 |
| slow指针 | 3 | 2 |
头指针 == slow指针,因此值为3
广告:
© 版权声明
THE END













暂无评论内容