环形链表找入口节点(Python and C++解法)

题目:

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

说明:不允许修改给定的链表。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle-ii

思路:

分三个环节完成:

  第一环节判断是否有环,使用快慢指针进行操作;

  第二环节计算环中节点的数量,如果有环,相遇点一定在环内,计算再次走到相遇点经过的结点数即可;

  第三环节找入口节点,在已知环的节点数量countCycle的前提下,使一个指针从头先走countCycle步,然后使另一个指针从头同步开始走,它们的相遇点就是环的入口点,因为nodeA先走countCycle步后离入口点的距离与此时B离入口点的距离相同。

Python解法:

 1 class ListNode:
 2     def __init__(self, x):
 3         self.val = x
 4         self.next = None
 5 
 6 class Solution:
 7     def detectCycle(self, head: ListNode) -> ListNode:
 8         slow = head
 9         fast = head
10         while fast and fast.next:
11             slow = slow.next
12             fast = fast.next.next
13             if fast == slow:
14                 meetNode = fast  # 相遇点
15                 break  # 找到相遇点后跳出循环
16         if fast == None or fast.next == None:
17             return None  # 链表没有环
18 
19         slow = meetNode.next
20         countCycle = 1  # 计算环的节点数量
21         while slow != meetNode:
22             countCycle += 1
23             slow = slow.next
24 
25         nodeA = head
26         nodeB = head
27         while countCycle:
28             nodeA = nodeA.next
29             countCycle -= 1
30         while nodeA != nodeB:  # 再次相遇节点就是入口节点
31             nodeA = nodeA.next
32             nodeB = nodeB.next
33         return nodeA

C++解法:

 1 struct ListNode {
 2      int val;
 3      ListNode *next;
 4      ListNode(int x) : val(x), next(NULL) {}
 5  };
 6 
 7 class Solution {
 8 public:
 9     ListNode *detectCycle(ListNode *head) {
10         // 判断是否有环
11         ListNode *slow = head;
12         ListNode *fast = head;
13         ListNode *meetNode;
14         while (fast && fast -> next) {
15             slow = slow -> next;
16             fast = fast -> next -> next;
17             if (fast == slow) {
18                 meetNode = fast;
19                 break;                
20             }
21         }
22         if (fast == NULL || fast -> next == NULL)
23                 return NULL;
24         // 计算环中节点的数量
25         int countCycle = 1;
26         slow = meetNode -> next;
27         while (slow != meetNode) {
28             slow = slow -> next;
29             countCycle += 1;
30         }
31 
32         // 找入口节点
33         ListNode *nodeA = head;
34         ListNode *nodeB = head;
35         while (countCycle--)
36             nodeA = nodeA -> next;
37         while (nodeA != nodeB) {
38             nodeA = nodeA -> next;
39             nodeB = nodeB -> next;
40         }
41         return nodeA;
42     }
43 };
posted @ 2020-07-03 16:34  孔子?孟子?小柱子!  阅读(410)  评论(0编辑  收藏  举报