24 day4 两两交换链表中的节点删除链表倒数第n个节点(19)环形链表(1

一、两两交换链表中的节点
要求:两两交换相邻节点,返回交换之后的链表
public class Test1 {static class ListNode {int val;ListNode next;ListNode() {}ListNode(int val) { this.val = val; }ListNode(int val, ListNode next) { this.val = val; this.next = next; }}public static ListNode swapPairs(ListNode head) {ListNode dummyNode = new ListNode(0);dummyNode.next = head;ListNode prev = dummyNode;while (prev.next != null && prev.next.next != null) {ListNode temp = head.next.next; // 缓存 nextprev.next = head.next;// 将 prev 的 next 改为 head 的 nexthead.next.next = head;// 将 head.next(prev.next) 的next,指向 headhead.next = temp;// 将head 的 next 接上缓存的tempprev = head;// 步进1位head = head.next;// 步进1位}return dummyNode.next;}public static void main(String[] args) {ListNode head = new ListNode(1);ListNode node2 = new ListNode(2);ListNode node3 = new ListNode(3);ListNode node4 = new ListNode(4);head.next = node2;node2.next = node3;node3.next = node4;swapPairs(head);}
二、删除链表的倒数第n个节点
要求:给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点
思路:使用双指针,快慢指针,首先快指针走n+1步,然后两个一块移动,直到fast指向为空,然后slow.next指向下一个节点
public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dumm = new ListNode(0);dumm.next = head;ListNode fast = dumm;ListNode slow = dumm;for(int i = 0;i
注:注意java里的栈和堆的分布,以及是否创建新的实例
三、环形链表
要求:给定一个链表,返回链表开始入环的第一个节点 。如果链表无环,则返回null
解法:快慢指针,分别定义fast和slow指针,从头结点出发,fast每次移动两个节点,slow每次移动一个节点,若是在途中相遇,说明链表有环
假设从头结点到环形入口节点 的节点数为x 。环形入口节点到 fast指针与slow指针相遇节点 节点数为y 。从相遇节点 再到环形入口节点节点数为 z 。
那么相遇时: slow指针走过的节点数为:x + y,fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针,(y+z)为 一圈内节点的个数A 。
因为fast指针是一步走两个节点,slow指针一步走一个节点,所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:
(x + y) * 2 = x + y + n (y + z)
两边消掉一个(x+y):x + y = n (y + z)
x = (n - 1) (y + z) + z
因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离 。
当n=1时,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点,那么当这两个指针相遇的时候就是 环形入口的节点 。
n>1,fast指针在环形转n圈之后才遇到slow
在推理过程中,大家可能有一个疑问就是:为什么第一次在环中相遇,slow的 步数 是 x+y 而不是 x + 若干环的长度 + y 呢?
即文章链表:环找到了,那入口呢?(opens new )中如下的地方:

24  day4 两两交换链表中的节点删除链表倒数第n个节点(19)环形链表(1

文章插图
首先slow进环的时候,fast一定是先进环来了 。
如果slow进环入口,fast也在环入口,那么把这个环展开成直线,就是如下图的样子:
可以看出如果slow 和 fast同时在环入口开始走,一定会在环入口3相遇,slow走了一圈,fast走了两圈 。
重点来了,slow进环的时候,fast一定是在环的任意一个位置,如图:
那么fast指针走到环入口3的时候,已经走了k + n 个节点,slow相应的应该走了(k + n) / 2 个节点 。
因为k是小于n的(图中可以看出),所以(k + n) / 2 一定小于n 。