Linked list to identify an entry node in the ring

Foreword

  Today brush "to prove safety offer" programming problem, meet a very interesting topic, called entry node in the ring list , write a blog about it.


description

  Given a list, at most one ring in this list, it is required: if the list has a ring, the ring entry node is returned, if there is no loop, return null .


Thinking

  We can set two pointers to solve this problem: a 快指针fast, each time to move forward two nodes, one 慢指针loweach time a node to go forward; we first need to know a conclusion: two hands fast and slow moving forward, If the list has a ring, then the two pointers will be met ;

  Here to clear three names:

  • 头节点: Represents the list of the first node;
  • 环入口节点: A ring if the list, the process proceeds to a node of the first ring;
  • 相遇点: Meet node pointer speed;

  We set up three variables to solve this problem:

  • Variables a: 头节点the 环入口节点distance;
  • Variable b: from 环入口节点the forward direction to the list in the 相遇点distance;
  • Face c: from 相遇点along the chain direction of 环入口节点distances;

  Therefore, the length of the list = a + b + c, while the chain length is C + B ;

  画个图,把上面说的变量和名称都标记上,我们不难看出,从开始到两个指针相遇,慢指针low走过的距离为a+b,而快指针fast走过的距离为a + k×(b+c) + b,其中k是一个整数,且k>0(因为如果k==0,那快慢指针走过的距离就相等了);快指针fast每次前进两个节点,而慢指针low每次前进一个节点,所以我们可以得到一个结论:相同时间内,快指针的走的路程是慢指针的两倍

  根据以上结论,我们可以得到一个公式:2×(a+b) == a + k × (b+c) + b,而这个公式可以进行化简,过程如下:

2×(a+b) == a + k × (b+c) + b;
2a + 2b == a + k × (b+c) + b;
a + b == k × (b+c);
a == k × (b+c) - b;
a == (k-1) × (b+c) + c;  // 最终结果

  经过一系列化简,我们可以得到a == (k-1) × (b+c) + c,而上面我们说过,(b+c)就是链表中环的长度,所以这个公式可以解释为:从链表头节点到环入口节点的距离,等于环长度的k-1倍,再加上从相遇点到环入口节点的距离

  上面的解释说明了什么?说明:两个指针,一个从链表头节点沿着链表向前走,另一个从快慢指针相遇点沿着链表向前走,最后它们会在环入口节点相遇(这里要好好理解一下);我们可以想象一下,指针在相遇点时,根据上面的最终结果,要向前走(k-1) × (b+c) + c这么长,而我们又知道,(b+c)就是环的长度,走一个b+c,就是饶了一圈,又回到了相遇点,所以当走完(k-1) × (b+c),其实又回到了相遇点;而这时,我们还要再向前走c个单位,c我们在上面已经说过了,就是相遇点到环入口的距离,所以走完c,指针就到了环入口了;而a我们也说过了,它是头节点走到环入口的距离。所以,才有了上面的说明。

  所以,这道题目的求解步骤就出来了:设置一个快指针fast,每次向前走两个单位,设置一个慢指针low,每次向前走一个单位,当这两个指针相遇,到达相遇点时,我们将设立一个指针指向链表头节点,另一个指针指向相遇点,两个指针速度均为1,沿着链表前进,最后它们相遇的位置,就是环入口节


代码

public ListNode EntryNodeOfLoop(ListNode pHead) {
    if(pHead == null) {
        return null;
    }
    // 设置快慢指针,快指针一次走两步,慢指针一次走一步
    ListNode fast = pHead;
    ListNode low = pHead;
    do {
        // 快指针先走一步
        fast = fast.next;
        // 若fast为null,表示没环,直接return空
        if(fast == null) {
            return null;
        }
        // 若不为null,再向前走一步
        fast = fast.next;
        // 慢指针向前走一步
        low = low.next;
    }while(fast != null && fast != low);

    // low指针指向链表头节点,fast指针不变,还是在相遇点
    // 两个指针速度均为1,向前走,再次相遇的点就是环入口节点
    low = pHead;
    while(low != fast) {
        low = low.next;
        fast = fast.next;
    }
    return low;
}

Guess you like

Origin www.cnblogs.com/tuyang1129/p/12194656.html