代码随想录算法训练营第四天: 24.两两交换链表中的节点 19.删除链表的倒数第N个节点 160(面试题).链表相交 142.环形链表II
24.两两交换链表中的节点
要点 : 把要操作的节点单独用指针标出来, 思路会更清晰
class Solution {
public ListNode swapPairs(ListNode head) {
//普通方法
ListNode dummy = new ListNode(0,head);
ListNode cur = dummy;
while(cur.next != null && cur.next.next != null){
ListNode node1 = cur.next;
ListNode node2 = cur.next.next;
cur.next = node2;
node1.next = node2.next;
node2.next = node1;
cur = cur.next.next;
}
return dummy.next;
}
}
递归 :
第一步 : 假设后面已经处理好,如何处理当前节点
第二步 : 分析什么条件下终止
第三步 : 标出有关返回值的操作节点如head , head.next ; 后面一团看作整体标出返回值对应节点,逐步分析操作
class Solution {
public ListNode swapPairs(ListNode head) {
//递归
if(head == null || head.next == null){
return head;
}
head.next.next = swapPairs(head.next.next);
ListNode temp = head.next;
head.next = head.next.next;
temp.next = head;
head = temp;
return head;
}
}
19.删除链表的倒数第N个节点
双指针:利用相对位置 , 得到倒数第n个节点的前一个节点的位置
屡次犯错 : 有dummy的返回不是head而是dummy.next
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode fast = dummy;
ListNode slow = dummy;
for(int i = 0; i <= n; i++){
fast = fast.next;
}
while(fast != null){
fast = fast.next;
slow = slow.next;
}
//注意判断空指针
if(slow.next != null){
slow.next = slow.next.next;
}
return dummy.next;
}
}
160(面试题).链表相交
- 假设链表
A
的长度为a
,链表B
的长度为b
,相交部分的长度为c
。 - 指针
p1
走过的总路径长度为a + (b - c)
,指针p2
走过的总路径长度为b + (a - c)
。 - 由于
a + (b - c) = b + (a - c)
,两个指针最终会在相交节点相遇。 - 若不相交, c = 0, 则总路径为 a + b, 即会在null相遇
(版本二) 合并链表实现同步移动
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// p1 指向 A 链表头结点,p2 指向 B 链表头结点
ListNode p1 = headA, p2 = headB;
while (p1 != p2) {
// p1 走一步,如果走到 A 链表末尾,转到 B 链表
if (p1 == null) p1 = headB;
else p1 = p1.next;
// p2 走一步,如果走到 B 链表末尾,转到 A 链表
if (p2 == null) p2 = headA;
else p2 = p2.next;
}
return p1;
}
}
142.环形链表II
两个问题 : 是否有环 and 入口在哪
**是否有环 : **快慢指针法 : 快指针和慢指针一定会在环中相遇
**入口在哪 : **根据公式 (x + y) * 2 = x + y + n (y + z) 可以得出 x = (n - 1) (y + z) + z
说明如果有关指针从头出发,另一个指针从相遇的位置出发 , 他们一定会在入口相遇
public class Solution {
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 p1 = head;
ListNode p2 = fast;
while(p1 != p2){
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
}
return null;
}
}