LeetCode: Linked List Cycle ii 解题报告

 Linked List Cycle ii

  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?

  SOLUTION 1:

  最开始的想法和 Linked List Cycle这一题一样。

  SOLUTION 2:

  同样是两个指针,一快一慢,相遇时跳出循环,只要循环结束时fast不为空,即有环。

  (fast != NULL && fast->next != NULL)或者(fast != slow)

  显然后一种写比较简洁。

  然后让链表头和slow一起按照相同速度移动,相遇的点就是环开始的地方。

  设链表头到两个指针相遇的地方长度为 A, 环的长度是 B.

  相遇的时候,

    slow的路程 Ls = A + k1*B; (k1 = 0,1,2...)

    fast的路程 Lf = A + k2*B; (k2 = 1,2,3...  k1<k2)

    fast速度是slow的2倍 2*Ls = Lf;

    Lf - Ls = (k2-k1)*B = Ls = A + k1*B;

    即    A = (k2-2*k1)*B

    设两个指针相遇的地方距离环的头是x;

    则 A-x = (k2-2*k1)*B

    而slow提前了x步。

 

 1 ListNode *detectCycle(ListNode *head) {
 2             if(head == NULL || head->next == NULL)
 3                 return NULL;
 4             ListNode *slow = head->next;
 5             ListNode *fast = head->next->next;
 6             while(fast && fast->next){
 7                 if(slow == fast)
 8                     break;
 9                 slow = slow->next;
10                 fast = fast->next->next;
11             }
12 //  if(fast != NULL && fast->next->next != NULL) is OK too.
13             if(slow != fast) return NULL;
14             fast = head;
15             while(fast!= slow){
16                 fast= fast->next;
17                 slow = slow->next;
18             }
19             return slow;
20     }
View Code

   SOLUTION 3:

    这种解法和第二种本质区别,只是这种做法将问题分解为1)是否有环 2)若有,则找两个链表的交点;若无,则返回NULL;

    这样将问题就能联系到之前的find intersection的问题了。解法来自 prataap89 (490 points)在讨论区的分享。

    The solution begins by first finding out if there is a cyle or not. If no cycle then return null. To find out the cycle use the slow, fast pointer technique. Once it has been established that cycle exists, find out the distance of the intersect node from the head of the list. Also find out the size of the loop. Now the question reduces to finding the common element in two linked lists. One list starts at head, and the other one starts at intersect node. To do this align the nodes such that they are both the same distance away from the end(intersect). Once this is done, you just have to increment and check if the nodes are equal or not.

    

 1 public ListNode detectCycle(ListNode head) {
 2         if (head == null) return head;
 3         //first check whether cycle exists or not
 4         ListNode first, second;
 5         first = second = head;
 6         while(true){
 7             first = first.next;
 8             if (second.next != null) second = second.next;
 9             else return null;
10             if (second.next != null) second = second.next;
11             else return null;
12             if (first == second) break;//list contains a cycle break
13         }
14 
15         //cycle exists store the intersect node
16         ListNode intersect = first;
17         first = head;
18         int k = 1;//the distance of the intersect node from head
19         while(true){
20             if (first == intersect) break;
21             first = first.next;
22             k++;
23         }
24         //这里找交点的方法如果用将两个链表形成环的办法,则解法与SOLUTION2相同
25         //the intersection is at distance k away from the head;
26         //now get the size of the loop
27         int s = 0;first = intersect;
28         while(true){
29             first = first.next;
30             s++;
31             if (first == intersect) break;
32         }
33         //s is the size of the loop now
34 
35         //now the question reduces to find the first intersecting element
36         //of two linked lists, list1 starts at head, list2 starts at intersect now
37 
38         //the first step is to align the nodes so they are at the same distance from the end(intersect node)
39         first = head;second = intersect;
40         if (s > k){
41             for(int i = s; i < k;i++)
42                 second = second.next;
43         }else{
44             for(int j = k; j < s; j++)
45                 first = first.next;
46         }
47         while(true){
48             if (first == second) return first;
49             first = first.next;
50             second = second.next;
51         }
52     }     
View Code

 

 

 

    

 

转载于:https://www.cnblogs.com/Pseudocnblog/p/4331247.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值