一、两两交换链表中的节点
问题要点
要清晰多个指针的意义,其中temp用来判断和指向后面的两个节点,然后实现两两交换
/**
* 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 dummyHead = new ListNode(0, head)
let temp = dummyHead // 指向后面的两个需要交换的节点
while(temp.next && temp.next.next) {
let pre = temp.next
let cur = temp.next.next
pre.next = cur.next
cur.next = pre
temp.next = cur
temp = pre
}
return dummyHead.next
};
二、删除链表的倒数第N个节点
问题要点
思路是快慢指针,快指针先走n步,然后慢指针和快指针同步,直到快指针走到倒数第二个节点,慢指针走到目标节点的前一个节点
或者快指针先走n+1步,,然后慢指针和快指针同步,直到快指针走到最后一个节点,慢指针走到目标节点的前一个节点
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
let dummyHead = new ListNode(0, head)
let fast = dummyHead
let slow = dummyHead
while(n-- >= 0) {
fast = fast.next
}
// fast走到了最后一个节点
// slow走到了目标节点的前一个节点
while(fast) {
slow = slow.next
fast = fast.next
}
slow.next = slow.next.next
return dummyHead.next
};
/**
* 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
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
let dummyHead = new ListNode(0, head)
let fast = dummyHead
let slow = dummyHead
while(n--) {
fast = fast.next
}
// fast走到了倒数第二个节点
// slow走到了目标节点的前一个节点
while(fast.next) {
slow = slow.next
fast = fast.next
}
slow.next = slow.next.next
return dummyHead.next
};
三、链表相交
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
if(!headA || !headB) {
return null
}
let lenA = getLenth(headA)
let lenB = getLenth(headB)
let curA = headA, curB = headB
if(lenA < lenB) {
[lenA, lenB] = [lenB, lenA]; // 这个分号是必须得
[curA, curB] = [curB, curA]
}
let i = lenA - lenB
while(i--) {
curA = curA.next
}
while(curA && curA !==curB){
curA = curA.next
curB = curB.next
}
return curA
};
function getLenth(head) {
let size= 0
let cur = head
while(cur) {
size++
cur = cur.next
}
return size
}
var getIntersectionNode = function(headA, headB) {
if(!headA || !headB) {
return null
}
let curA = headA
let curB = headB
while(curA !== curB) {
curA = curA === null ? headB : curA.next
curB = curB === null ? headA : curB.next
}
return curA
};
四、环形链表2
问题要点
首先要判断链表是否有环,slow和fast必须同时从head开始走,fast走两步,slow走一步
数学公式计算:当fast进入环一圈后,必然在slow进入环的一圈内追上,当fast追上slow的时候,其距离环入口的距离等于从head到环入口的距离
/**
* 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
}
// slow和fast必须同时从head开始走,fast走两步,slow走一步
let slow = head.next
let fast = head.next.next
while(slow !== fast) {
if(!fast || !fast.next) {
return null
}
slow = slow.next
fast = fast.next.next
}
slow = head
while(slow !== fast) {
slow = slow.next
fast = fast.next
}
return slow
};