24. 两两交换链表中的节点
解题思路
虚拟头节点
使用虚拟头节点来解决需要单独逻辑处理第一个节点的地方(交换问题,新增、删除)
使用临时变量记录节点
代码
var swapPairs = function(head) {
var dummyhead = new ListNode();
dummyhead.next = head,
cur = dummyhead;
while(cur.next != null && cur.next.next != null){
var temp1 = cur.next,
temp2 = cur.next.next.next;
cur.next = cur.next.next;
cur.next.next = temp1;
temp1.next = temp2;
cur = cur.next.next;
}
return dummyhead.next;
};
19.删除链表的倒数第N个节点
解题思路
虚拟节点 + 快慢指针
**快指针为什么要多走一步**
- 确保慢指针指向前驱节点
- 如果快指针只移动N步,当快指针到达末尾时,慢指针会指向待删除节点本身,而不是其前驱节点。
- 例如:删除倒数第2个节点时,快指针走N+1=3步后,慢指针最终会停在倒数第3个节点(即前驱节点)。
代码
var removeNthFromEnd = function(head, n) {
//新建虚拟头节点,便于新增和删除
var dummyhead = new ListNode();
dummyhead.next = head;
// 快指针比慢指针先走 n + 1 步,之后快慢指针一起走
// 那么最后 slow 指向的是删除结点的前一个节点
var fast = dummyhead ,slow = dummyhead;
while(n+1){
fast = fast.next;
n--;
}
while(fast != null){
fast = fast.next;
slow = slow.next;
}
// 这时候 slow 指向的是删除结点的前一个节点
// 删除倒数第 n 个节点
slow.next = slow.next.next;
return dummyhead.next
};
142.环形链表II
解题思路
代码
var detectCycle = function(head) {
var pre = head;
var fas = head, index = null;
while(fas && fas.next && fas.next.next){
fas = fas.next.next;
pre = pre.next;
if(fas === pre){
index = fas;
break;
}
}
let index2 = head;
while(index!= null && index !== index2){
index = index.next;
index2 = index2.next;
}
return index;
};