JS 常见的链表操作
目录
1.单链表反转
2.链表中环的检测 相关问题
3.两个有序的链表合并
4.删除链表倒数第 n 个结点
5.求链表的中间结点
1. 单链表反转
// 判断对象是否为空
function isEmptyObject(obj) {
for (var name in obj) {
return false;
}
return true;
}
function ReverseList(pHead) {
if (isEmptyObject(pHead)) {
return false;
}
var pre = pHead;
var PreNext = null;
while (pre.next != null) {
preNext = pre.next;
pre.next = preNext.next;
preNext.next = pHead;
pHead = preNext;
}
return pHead;
}
反转链表的思路:1-2-3-4-5,先将2换到第一个,变为:2-1-3-4-5。然后将3换到第一个,3-2-1-4-5。
以此类推。其中,pre始终指向1,preNext指向pre的下一个,即本轮需要换到第一个的数。
如此列表:
1-2-3-4-5
2-1-3-4-5
3-2-1-4-5
4-3-2-1-5
5-4-3-2-1
2. 链表中环的检测 相关问题
关于链表中环的检测,相关问题一般有如下几种:
- 给定一个单链表,判断其中是否有环的存在
- 如果存在环,找.出环的入口点
- 如果存在环,找出环上结点的个数
- 如果存在环,求出链表的长度
- 如果存在环,求出环上距离任意一个结点最远的结点(环的对面结点问题)
- 判断两个无环链表是否相交
- 如果相交,求出第一个相交结点
针对如上七种问题,下面逐一进行分析并写出相应实现代码。
(1)判断是否有环
问题分析:
对于这个问题,有一种非常巧妙的“快慢指针”的方法,就是定义两个指针:fast和slow,最初的时候fast和slow都指向链表的初始结点head,然后每一次操作,fast向前走两步,slow向前走一步。
因为fast比slow移动快,如果有环,那么fast一定会先进入环,而slow后进入环。当两个指针都进入环后,经过一定次数的操作,fast和slow最终会在环上相遇,并且一定是在slow绕环走完一圈之前相遇。
如图所示,slow进入环时,fast可能处于图示状态,然后每次操作,slow会向前走一步,而fast会向前追两步。因此每次操作完fast到slow的距离都会缩短一步,5、4、3、2、1…直到相遇。
又因为同一个环中,slow和fast的距离不可能大于环的总长度,所以fast和slow一定会在slow走完一圈之前相遇。
特殊情况:开始时,slow和fast就在环的入口处,这样相遇时,slow刚好走完一圈。
实现代码:
function isExitLoop(head) {
if (head === null || head.next === null) {
return false;
}
let slow = head;
let fast =<