链表-找出该链表的环的入口结点(思路和代码实现)

KLQ 2020-04-14 15:33:58 java常见问答 10453

对于链表你了解多少呢?下面要给大家带来的是关于找出该链表的环的入口结点的思路和代码实现。

题目:

一个链表,假如,其中包括了环,那么,请找出这个链表的环的入口结点,否则,输出null。

思路1:

首先,找到环中的相汇点。

分别用p1,p2指向链表头部,p1每走一步,p2每走二步,直到p1==p2找到在环中的相汇点。

接着,要找到环的入口。

接着上面一步,在p1==p2的时候,p2所经过节点数为2x,p1所经过节点数为x,设环中有n个节点,p2比p1多走一圈有2x=n+x; n=x;能够看出p1实际走了一个环的步数,再让p2指向链表头部,p1位置不改变,p1,p2每次走一步直到p1==p2; 这个时候p1指向环的入口。

代码实现:

public class Solution
{
    ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if (pHead == null || pHead.next == null)
            return null;
        ListNode p1 = pHead;
        ListNode p2 = pHead;
        while (p2 != null && p2.next != null)
        {
            p1 = p1.next;
            p2 = p2.next.next;
            if (p1 == p2)
            {
                p2 = pHead;
                while (p1 != p2)
                {
                    p1 = p1.next;
                    p2 = p2.next;
                }
                if (p1 == p2)
                    return p1;
            }
        }
        return null;
    }
}

思路2:

先讲一个定理:两个指针一个fast、一个slow同时从一个链表的头部出发

fast一次走两步,slow一次走一步,假如这个链表有环,那么两个指针一定会在环内相遇

这个时候就只要将其中的一个指针重新指向链表头部,另外一个不变(还在环内),

这次两个指针一次走一步,相遇的地方就是入口节点。

代码实现:

public class Solution
{
    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        ListNode fast = pHead;
        ListNode slow = pHead;
        while (fast != null && fast.next != null)
        {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow)
                break;
        }
        if (fast == null || fast.next == null)
            return null;
        fast = pHead;
        while (fast != slow)
        {
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }
}

思路3:

时间复杂度是O(n),两个指针,一个在前面,另外一个在后面紧邻着这个指针。

两个指针同时向前移动,每移动一次,前面的指针的next指向NULL。

表示:访问过的节点都断开,最后到达的那个节点一定是尾节点的下一个,

也就是循环的第一个。

那么,这个时候已经是第二次访问循环的第一节点了,第一次访问的时候我们已经让它指向了NULL,

所以到此结束。

代码实现:

class Solution
{
    public:
        ListNode * EntryNodeOfLoop(ListNode * pHead)
        {
            if (!pHead - > next)
                return NULL;
            ListNode * previous = pHead;
            ListNode * front = pHead - > next;
            while (front)
            {
                previous - > next = NULL;
                previous = front;
                front = front - > next;
            }
            return previous;
        }
};

除了以上的3种思路和代码实现方式之外,还有很多的思路和方法都是可以实现的,以上的内容可以供给参考,除此之外,大家也可以更多的去思考一下。

想了解更多的相关Java实例内容,可以继续关注本站了解。有更多的Java实例可以分享给大家。