python algorithm diary (list series) _leetcode 142. circular linked list II

Given a list, return the first node into the beginning of the chain ring. If chain acyclic, null is returned.

To show the list given ring, we integer pos connected to the end of the list to represent the position of the list (index starts from 0). If pos is -1, the ring is not on this list.

Description: Do not allow to modify the given list.

Example 1:

Input: head = [3,2,0, -4] , pos = 1
Output: tail connects to node index 1
explained: the list has a ring tail portion connected to a second node.

Example 2:

Input: head = [1,2], pos = 0
Output: tail connects to node index 0
explanation: the list has a ring, which is connected to the tail of the first node.

Example 3:

输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。

Source: stay button (LeetCode)
link: https: //leetcode-cn.com/problems/linked-list-cycle-ii

A method of: using a set of properties (set) of the unordered sequence of elements will not be repeated. The presence of visited node set, the extension of the circular linked list, I practice

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return None
        visited = set()
        while(head):
            if head in visited:
                return head
            else:
                visited.add(head)
            head = head.next
        return None

Method two: the speed of the pointer. Reference LeetCode official answer
link: https: //leetcode-cn.com/problems/linked-list-cycle-ii/solution/huan-xing-lian-biao-ii-by-leetcode/
Phase One: If the list is circular, a pointer slow step, fast moving twice the pointer, the pointer will always meet the speed of a node in the ring. Imagine, in a ring in the run, always run fast to catch up with the slower runners. Thus it proved to meet the speed of a ring pointer list.

Phase II: After the first encounter, encounter slow pointer still points to the location, fast pointer to the starting position. Fast pointer changes only take one step, the second speed pointer always meet ingress node. (Hard to think of this law, the following do to prove)

image.png

Photos from the official answer LeetCode

F, starting from the inlet to the ring, h is the speed meet pointer position. H inlet ring into the ring in two parts a and b.

When the large ring, a + b> F case:

H speed pointer points meet, slow down the pointer F + a, it is to walk faster than a pointer ring, go F + a + b + a. Slow walking distance since the pointer is a pointer fast half, 2 (F + a) = F + 2a + b, so F = b. I.e. the ring to walk a + b = F + a, b = F. I.e. fast start position pointer go to step 1 F., Slow pointer position h, go to step 1 B, they will meet at the entrance position.

When the ring is very small, F the case where long distance:

Small ring, it may soon go the pointer n rings. 2 (F + a) = F + a + n (a + b), F = (n-1) (a + b) + b.

A walking distance of F, because a lot of laps around + b will still come to the entrance and another encounter.

A proof of the comments:

@ Vibration from the  https://leetcode-cn.com/u/zhen-zhi/ , his analysis that when the ring is large, a + b> F case.

Figure 1: When the slow slow down the pointer n go inlet ring, 2n come down fast fast current pointer position.

Figure 2: when n + b slow down the pointer come current position, the current position n from the inlet ring. At this time, the pointer fast walking 2 (n + b), to meet with the slow pointer. Let the pointer quickly back to the start node, the same steps can be met in n go inlet ring.

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return None
        slow = fast = head
        while(fast.next.next and slow.next):
            fast = fast.next.next
            slow = slow.next
            if not fast.next or not slow.next:
                return None
            if fast == slow:
                cur = slow
                pre = head
                while(cur!=pre):
                    cur = cur.next
                    pre = pre.next
                return cur
        return None

 

Published 44 original articles · won praise 0 · Views 1904

Guess you like

Origin blog.csdn.net/weixin_39331401/article/details/104607755