代码随想录训练营第四天|24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,160.相交链表,142.环形链表II
24. 两两交换链表中的节点
文章
思路
两个指针指向当前要交换的两个节点,一个指针指向这两个节点前面的节点,一个指针指向这两个节点后面的节点。交换之后拼回去。
代码
class Solution {
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode dummy = new ListNode(0, head);
ListNode prev = head;
ListNode post = head.next;
ListNode root = dummy;
ListNode temp;
while (true) {
temp = post.next;
root.next = post;
post.next = prev;
prev.next = temp;
root = prev;
prev = temp;
if (prev == null || prev.next == null) {
break;
}
post = temp.next;
}
return dummy.next;
}
}
19.删除链表的倒数第N个节点
文章
思路
快慢指针。快指针比慢指针先行N步,快指针到最后一个节点停止,此时慢指针指向待删除节点的前驱节点,便于执行删除操作。
代码
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode fast = dummy;
ListNode slow = dummy;
while (n > 0) {
fast = fast.next;
--n;
}
while (fast.next != null) {
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
160.相交链表
文章
思路
先分别遍历两个链表,计算长度差。
再遍历,让长链表的指针先行长度差的步数,然后开始并行,检查是否有相同节点。
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int diffAB = 0;
ListNode pA = headA;
ListNode pB = headB;
while(pA != null || pB != null) {
if (pA == pB) {
return pA;
}
if (pA == null) {
++diffAB;
pB = pB.next;
} else if (pB == null) {
--diffAB;
pA = pA.next;
} else{
pA = pA.next;
pB = pB.next;
}
}
pA = headA;
pB = headB;
if (diffAB > 0) {
while (diffAB > 0) {
pB = pB.next;
--diffAB;
}
}
if (diffAB < 0) {
while (diffAB < 0) {
pA = pA.next;
++diffAB;
}
}
while (pA != null) {
if (pA == pB) {
return pA;
}
pA = pA.next;
pB = pB.next;
}
return null;
}
}
142.环形链表II
文章
思路
不会做,看题解。
快慢指针,快指针一步走2,慢指针一步走1,如果有环则一定相遇。设头结点到环入口距离为
l
l
l 环入口到相遇位置距离为
x
x
x,环一圈长度为
r
r
r ,易知慢指针走过的路程为
l
+
x
+
n
r
l + x + nr
l+x+nr,快指针走过的路程为
l
+
x
+
(
n
+
1
)
r
l + x + (n + 1)r
l+x+(n+1)r ,而快指针走过的路程一定是慢指针的2倍,从而有
l
+
x
=
r
l + x = r
l+x=r,则有
l
=
r
−
x
l = r - x
l=r−x。
我就卡在这里了,不知道
r
r
r ,不知道
x
x
x,我咋求
l
l
l。
万万没想到,不是算出来的,是数出来的。
l
=
r
−
x
l = r - x
l=r−x 这个等式的含义是:从头结点到环入口的距离等于慢指针继续走完当前这一圈剩下的路程。这意味着如果此时有另一个指针从头结点出发,慢指针与其同步推进,二者相遇时位置应该恰好是环入口。
代码
public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null || head.next == null) {
return null;
}
ListNode slow = head;
ListNode fast = head;
ListNode ptr = head;
int s = 0;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
++s;
if (fast == null || fast.next == null) {
return null;
}
if (slow == fast) {
// System.out.println(slow.val);
break;
}
}
while (ptr != slow) {
slow = slow.next;
ptr = ptr.next;
}
return ptr;
}
}
总结
其实很巧的是,今天LeetCode推送的每日一题是141.环形链表也是链表的题目,我也做了,但是其中包含的要点完全被142.环形链表II覆盖,相当于无用功。
今天感觉环形链表和链表相交两个题目有一些共性,需要用一个指针先完成差距量,然后再用另一个指针从头出发寻找相遇的节点。