代码随想录算法训练营第第四天 | 24. 两两交换链表中的节点 、19.删除链表的倒数第N个节、面试题 02.07. 链表相交、142.环形链表II
- 两两交换链表中的节点
用虚拟头结点,这样会方便很多。
本题链表操作就比较复杂了,建议大家先看视频,视频里我讲解了注意事项,为什么需要temp保存临时节点。
题目链接/文章讲解/视频讲解: https://programmercarl.com/0024.两两交换链表中的节点.html
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*交换节点比较容易混乱,按步骤来
*/
var swapPairs = function(head) {
let ret = new ListNode(null,head);
let temp = ret;
while(temp.next&&temp.next.next){
let cur = temp.next.next;
let prev = temp.next;
prev.next = cur.next;
cur.next = prev;
temp.next = cur;
temp = prev;
}
return ret.next;
};
19.删除链表的倒数第N个节点
双指针的操作,要注意,删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点,建议先看视频。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0019.删除链表的倒数第N个节点.html
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* 关键在于怎么找到第n个节点的前一个节点
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
let dummy = new ListNode(null, head);
let fast = dummy;
let slow = dummy;
let count = 0;
while(count<=n){
fast = fast.next;
count++;
}
while(fast){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
head = dummy.next;
return head;
};
面试题 02.07. 链表相交
本题没有视频讲解,大家注意 数值相同,不代表指针相同。
题目链接/文章讲解:https://programmercarl.com/面试题02.07.链表相交.html
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
* 完全没想到方法,适合二刷
*/
var getIntersectionNode = function(headA, headB) {
let countA = 0;
let countB = 0;
let curA = headA;
let curB = headB;
while(curA){
countA++;
curA = curA.next;
}
while(curB){
countB++;
curB = curB.next;
}
let curA2 = headA;
let curB2 = headB;
if(countA<countB){
[curA2,curB2] = [curB2,curA2];
[countA,countB] = [countB,countA];
}
let i = countA - countB;
while(i--){
curA2 = curA2.next;
}
while(curA2 && curA2!==curB2){
curA2 = curA2.next;
curB2 = curB2.next;
}
return curA2;
};
142.环形链表II
算是链表比较有难度的题目,需要多花点时间理解 确定环和找环入口,建议先看视频。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0142.环形链表II.html
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*快慢指针结合数学题,
*另一种方法,用哈希保存访问过的节点,如果遍历时再次遍历到访问过的节点,则是入口。
*/
var detectCycle = function(head) {
if(!head || !head.next) return null;
let slow = head.next;
let fast = head.next.next;
while(fast&&fast.next&&fast!==slow){
fast = fast.next.next;
slow = slow.next;
}
if(!fast || !fast.next) return null;
slow = head;
while(slow!==fast){
slow = slow.next;
fast = fast.next;
}
return fast;
};