Day04–链表–24. 两两交换链表中的节点,19. 删除链表的倒数第 N 个结点,面试题 02.07. 链表相交,142. 环形链表 II
Day04–链表–24. 两两交换链表中的节点,19. 删除链表的倒数第 N 个结点,面试题 02.07. 链表相交,142. 环形链表 II
24. 两两交换链表中的节点
记录:三指针法,自己一次性做的。草稿纸画图。一定要画图。
思路:1、先解决(head == null || head.next == null)的情况,这样的话,剩下的情况都至少有两个节点
2、因为是修改链表,最好有个虚拟头结点。
3、pre等于要修改的前一个节点,left和right就是要交换的节点。
4、当pre没有下一个结点的时候可以退出了(当只有left没有right的时候也可以退出了,left不用和谁交换)
5,交换的三部曲。因为有三个指针,随便的顺序感觉都可以,画个图理解一下就可以了。把各个节点的next修改完之后,pre = left,就可以进入下一轮循环了。
class Solution {public ListNode swapPairs(ListNode head) {if (head == null || head.next == null) {return head;}ListNode preHead = new ListNode();preHead.next = head;ListNode pre = preHead;while (pre.next != null) {ListNode left = pre.next;ListNode right = null;if (left.next != null) {right = left.next;} else {break;}ListNode tem = right.next;pre.next = right;right.next = left;left.next = tem;pre = left;}return preHead.next;}
}
19. 删除链表的倒数第 N 个结点
记录:自己凭着记忆写出来的。不是背,而是看到这类题会做了。(ps:前几天刚做过)
思路:右指针先走n步,左指针再出发,当右指针到结尾的时候,左指针就是要删除的节点的前节点,刚好可以用left.next = left.next.next;
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {// 思路:右指针先走n步,左指针再出发,// 当右指针到结尾的时候,左指针就是要删除的节点的前节点,刚好可以用left.next = left.next.next;ListNode preHead = new ListNode();preHead.next = head;ListNode left = preHead;ListNode right = preHead;for (int i = 0; i < n; i++) {right = right.next;}while (right.next != null) {right = right.next;left = left.next;}left.next = left.next.next;return preHead.next;}
}
面试题 02.07. 链表相交
思路:// 要末端对齐
// 1.指针同时指向末尾
// 2. 长链先走gap步
// 当相等返回指针,当指针指向null则表示不相交,退出。
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 要末端对齐// 1.指针同时指向末尾// 2. 长链先走gap步// 当相等返回指针,当指针指向null则表示不相交,退出。ListNode pa = headA;ListNode pb = headB;int lenA = 0;int lenB = 0;// 这里不是pa.next != null,犯错了一次。while (pa != null) {pa = pa.next;lenA++;}while (pb != null) {pb = pb.next;lenB++;}if (lenB > lenA) {ListNode temp = headA;headA = headB;headB = temp;int tem = lenA;lenA = lenB;lenB = tem;}int gap = lenA - lenB;pa = headA;pb = headB;while (gap-- > 0) {pa = pa.next;}while (pa != null && pb != null) {if (pa == pb) {return pa;}pa = pa.next;pb = pb.next;}return null;}
}
142. 环形链表 II
记录:自己根据回忆写的,解题思路是记得的。但是“当fast与slow相遇之后,来一个temp=head,从头开始和slow走相同的步数就是起点了”,这个理论成立不会证明。或者说,就算记住了这题的证明,来一题类似的题目,自己也不会根据公式推理。
思路:// 思路:快指针2步/会合,慢指针1步/会合;
// 当快慢指针相遇的时候,定义一个temp指针从头走,慢指针也走,当slow==temp的时候,就是环的起点
// 查找一般是不用preHead的
public class Solution {public ListNode detectCycle(ListNode head) {// 思路:快指针2步/会合,慢指针1步/会合;// 当快慢指针相遇的时候,定义一个temp指针从头走,慢指针也走,当slow==temp的时候,就是环的起点// 查找一般是不用preHead的if (head == null || head.next == null) {return null;}ListNode fast = head;ListNode slow = head;while (fast != null || slow != null) {if (fast.next == null || fast.next.next == null) {return null;}fast = fast.next.next;slow = slow.next;if (fast == slow) {ListNode temp = head;while (temp != slow) {temp = temp.next;slow = slow.next;}return temp;}}return null;}
}