24. 两两交换链表中的节点
使用虚拟头节点的原因:head会随着交换而改变
需要考虑每层loop后prev和curr需要前进的数量(思考当前位置)
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) return head;
ListNode curr = head;
ListNode dummy = new ListNode(0);
ListNode prev = dummy;
while(curr != null && curr.next != null){
prev.next = curr.next;
curr.next = prev.next.next;
prev.next.next = curr;
prev = prev.next.next;
curr = curr.next;
}
return dummy.next;
}
19.删除链表的倒数第N个节点
需要思考所需指针数量,使用slow时,fast和slow之间的距离不一定为N,可调整为N+1
目的是方便移除元素,且与dummy head兼容
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null || head.next == null) return null;
ListNode fast = head;
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode slow = dummy;
while (n > 0){
fast = fast.next;
n--;
}
while(fast != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
160. 链表相交
思路:两个链表尾部对齐,从同一index开始
index: 使长链表的剩余部分和短链表相同
不能把while(lenA > lenB)的while loop简化成while(lenA-- > lenB)
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0, lenB = 0;
ListNode currA = headA, currB = headB;
while(currA != null){
lenA++;
currA = currA.next;
}
while(currB != null){
lenB++;
currB = currB.next;
}
currA = headA;
currB = headB;
while (lenA > lenB){
currA = currA.next;
lenA--;
}
while (lenB > lenA){
currB = currB.next;
lenB--;
}
while(currA != null){
if (currA == currB) return currA;
currA = currA.next;
currB = currB.next;
}
return null;
}
142.环形链表II
使用二倍速快慢指针确定环的存在性,以及环的长度
确认有环后,从起点设置新指针,新指针和slow指针会在环入口相遇
(slow指针已走路程为环的长度,还需total-length of ring可回到环的起点)
public ListNode detectCycle(ListNode head) {
ListNode fast = head, slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if (fast == slow){
ListNode curr = head;
while(curr != slow){
curr = curr.next;
slow = slow.next;
}
return curr;
}
}
return null;
}