Endless chain stay button 142-- II

The original title

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:

输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。

Example 2:

输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。

Example 3:

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

Advanced:

If you do not have extra space to solve this problem?

原题url:https://leetcode-cn.com/problems/linked-list-cycle-ii/

Problem-solving

Here stickers node structure provided by the subject, so that the following code will not repeat posted:

Definition for singly-linked list.
class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}

Use collection

Get the title when, at the beginning of thought is the use of a collection, storage has traversed the nodes, if access to null, instructions is not a ring; if you add fails, explained that it had been added, then it must be a ring, and the ring node is Entrance;

By the way, I think that the space occupied by the collection should not be great, because it only addresses stored application object, of course, the collection itself is a new object will take up extra space.

Let's look at the code:

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null) {
            return null;
        }

        ListNode current = head;
        Set<ListNode> set = new HashSet<>();
        while (current != null) {
            // 添加成功,则继续访问下一个节点
            if (set.add(current)) {
                current = current.next;
                continue;
            }

            // 添加不成功,说明重复
            return current;
        }

        return null;
    }
}

Submit OK, when executed by: 5 msmemory consumption: 37.7 MBbut only when submitted with a victory over 30.99%the java commit record, it seems necessary to optimize it.

Find the law

Before we determine whether there is a ring chain, it is final for equality by the speed pointer. Now, then, since the ring may not be connected end to end, only to find it once may not be enough, and need to continue to find the law.

We assume a slow start pointer traveled is x, then traveled on the fast pointer to 2x, namely:

s = x;
f = 2x;

If fast final pointer is null, then that is not a ring.

If fast, slow pointer is equal to the final point node, there is described a ring, and, FAST pointer to walk the length of the flow ratio of n rings pointer, then we assume that the length of the ring is b, it can be drawn:

f = x + nb;

It can be drawn:s = nb;

These are the most important conclusions, slow pointer in fact, have gone the length of the n rings. So, let us assume that the length from the head node to node is a ring entrance, then met node from the pointer speed walk a step, and ultimately where it would go?

Will eventually come to the entrance node ring, as (nb + a)can be understood as (a + nb)equivalent to starting from the head node, the node at the entrance to reach the ring, and walked around the ring n lap, so I will come to the entrance of the ring. So this time we find the entrance node of the ring.

Let's look at the code:

public class Solution {
    public ListNode detectCycle(ListNode head) {
        // 先利用快慢指针,如果最终能相遇,说明有环
        ListNode slow = head;
        ListNode fast = head;
        while (true) {
            // 快指针为null,说明没有环
            if (fast == null || fast.next == null) {
                return null;
            }

            // 慢指针移动一步
            slow = slow.next;
            // 快指针移动两步
            fast = fast.next.next;
            // 快慢指针相等,说明相遇
            if (fast == slow) {
                break;
            }
        }

        // 再用两个指针,一个从头结点出发,一个从相遇点出发,两个指针每次移动1步,两个指针相遇的地方为环的入口
        slow = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }

        return slow;
    }
}

Submit OK, when executed by: 1 msmemory consumption: 37.8 MBbut only when submitted with a victory over 55.14%the java commit record, Is there a more efficient way?

I found a code that executes with 0 ms, the discovery is, and I like this, I will submit its code again, and I found this to submit the same results. It seems that our algorithm is faster than, perhaps because the author earlier time, the test case is not so much as they are now, so do not worry about it.

to sum up

This question is above my answer process, I do not know if you understand. This question is not only to take advantage of the speed of the pointer, but also summed up the law, and ultimately solve, the test subject in general is a very logical thinking.

Are interested can visit my blog or follow me number of public, headline number, maybe there will be surprises.

https://www.death00.top/

Public number: Jian Cheng Road

Guess you like

Origin www.cnblogs.com/death00/p/12147923.html