LeetCode 解题报告 LinkedListCycleII

来源:互联网 发布:手机图片点击放大js 编辑:程序博客网 时间:2024/09/21 09:28

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Follow up:

Can you solve it without using extra space?

分析:

题目中要求求出一个循环链表的第一个循环结点,这个题目还要求不能外加空间。

其实这个题可以把他分成两步来做,一个是判断一个链表是不是有环,另一个是求两个链表的第一个交点

判断两个链表是不是有环的存在,就是两个指针,一个快,一个慢,如果两个指针能相遇,那就说明这个链表有环,否则没有环

求两个相交链表的第一个交点,可以分别遍历两个链表,求出其长度,然后让长链表先走对应的两个链表长度的差值步,然后两个链表同时走,

并判断俩结点是否相同,如果相同就返回这个结点

下面是上述思路的代码:

public class LinkedListCycleII {public ListNode detectCycle(ListNode head) {if(head == null)return null;//判断是否存在环ListNode node = head;ListNode fast = node,slow = node;while(fast.next != null && fast.next.next != null){fast = fast.next.next;slow = slow.next;if(fast == slow)break;}//无环if(fast.next == null || fast.next.next == null)return null;//有环,需要断开环fast = fast.next;slow.next = null;//现在有了两个链表,一个是head开头,一个是fast开头//找到两个链表的第一相交的结点//首先依次遍历两个链表,确定两个链表的长度,得到count = l1 - l2 的值,然后长链表先走//count步,之后两个同时走,并判断两个结点是否相同,如果相同就是第一个相交的结点return FindFirstNode(head,fast);}public ListNode FindFirstNode(ListNode l1,ListNode l2){//遍历两个链表,分别求长度int len1 = GetListLength(l1);int len2 = GetListLength(l2);int count = len1 - len2;if(count < 0){count = - count ;//令长链表先走,第一个变量放置长链表return FindNode(l2,l1,count);}elsereturn FindNode(l1,l2,count);}public int GetListLength(ListNode head){int len = 0;ListNode node = head;while(node != null){len ++;node = node.next;}return len;}public ListNode FindNode(ListNode h1,ListNode h2,int count){ListNode l1 = h1,l2 = h2;while(count-- != 0){l1 = l1.next;}while(l1 != null && l2 != null && l1 != l2){l1 = l1.next;l2 = l2.next;}ListNode result = l1;return result;}}

思路2:

上述思路简单明了,就是实现起来代码比较繁琐,当时我在A这个题的过程中,会遇到很多意想不到的错误,

下面就给出网上的另一种思路,真的是分析透彻了之后再代码实现会让代码更美

思路是这样的

首先当一个快指针和一个满指针在环内循环的时候,在他俩相遇之前,慢指针是不会循环一圈的,假设slow指针走了s步,那么fast指针就走了2s步,当然这其中fast指针走了n圈,假设一圈有r步,外加S步,假设这个链表的圈内共有r步,那么2s = s + nr

可以得出s = nr,由此可以看出当这个链表就只是一个环的时候,快慢指针会在head出相遇,fast指针转两圈,slow指针刚好转一圈

同时,我们假设从环的入口点到相遇点共有a步,从起点到环的入口点为x,整个链表的长度为L,则慢指针走的s步就为x+a, 那么:x+a = nr

= (n-1)r+r = (n-1)r + (L-x)

所以x = (n-1)r + (L-x-a)

L-x-a正好是从相遇点到环的入口点的距离, 那么从链表的头结点到环的入口结点的距离就等于(n-1)圈环内距离加上从相遇点到环的入口距离,

那么可以再设置一个指针slow2从链表的头结点开始,slow和slow2指针同时走一步,知道两个指针相同,就是环的入口地址

下面是代码:

public ListNode detectCycle2(ListNode head){ListNode fast = head,slow = head;while(fast != null && fast.next != null){slow = slow.next;fast = fast.next.next;if(fast == slow){ListNode slow2 = head;while(slow != slow2){slow = slow.next;slow2 = slow2.next;}return slow;}}return null;}


0 0
原创粉丝点击