经典题目——链表中环的入口结点

链表中环的入口结点

引例:给定一个链表,若其中包含环,则输出环的入口节点。若其中不包含环,则输出null。

在这里插入图片描述

给定如上所示的链表:
[1, 2, 3, 4, 5, 6]
2
注意,这里的2表示编号是2的节点,节点编号从0开始。所以编号是2的节点就是val等于3的节点。
则输出环的入口节点3.


本题所用到的方法是快慢指针扫描。
图1 循环链表示意图
设i指针速度为v,j指针速度为2v,两点在c点时第一次相遇。ab距离为x,bc距离为y,cb距离为z。设n为相遇时j所转的圈数。则在相遇时:
j走过的路径Sj = x + (y + z)*n + y;
i走过的路径Si = x + y;
由速度可知,二者的路径关系为Sj = 2 * Si;
即x + (y + z)*n + y = 2 * (x + y),整理得
x = (n - 1)(y + z) + z;
由于n是任意整数,不妨设为1,则x = z;
由此可知,j节点在c点再往前走x个长度即可到达b点。
为了节省内存,我们让i重新指向头结点,i和j同时往前以相同速度移动,当两者再次相遇时就找到了答案。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *entryNodeOfLoop(ListNode *head) {
        auto i = head, j = head;//i是慢的, j是快的
        while(i && j){
            i = i -> next;
            j = j -> next;
            if(!j) return NULL;
            j = j -> next;
            if(i == j){
                i = head;
                while( i != j){
                    i = i -> next;
                    j = j -> next;
                }
                return i;
            }
        }
        return NULL;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章