(1)LeetCode之 142.环形链表II

1、题目描述  142. 环形链表 II


        给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。

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

2、思路

        题目分两步,首先通过快慢指针的方法判断链表是否有环;然后如果有环,则寻找入环的第一个结点,下面是具体思路。

变量:fast 快指针,slow 慢指针,temp指向相遇结点
思路1:

         a)假设判断有环存在,如下图,链表的总长度为a + n,此时fast 和 slow 在 temp 结点相遇。
         b)接下来让 temp循环走一周,即得到了环的长度n。
         c)然后让fast和slow重新指向head,fast先走n个结点,然后再让fast和slow共同走a步,此时两个指针相遇,且因为fast走完了  n+a 一整个链表的长度所以走到了链表的尾部,即相遇点即为入环点出。

 思路2:
         其实,在思路1的问题上我们忽略了一个问题,看思路2的图。即其实从相遇点到入环点的距离就等于从头结点到入环点的距离;所以思路1的第 c 步中没必要先让fast走n步,直接让fast和slow分别从相遇点y和头结点同时同步长出发,相遇点即为入环点。

3.代码实现

C++实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head == nullptr)
            return nullptr;
        ListNode* slow = head; //一次走一个结点
        ListNode* fast = head; //一次走两个结点
        ListNode* temp = nullptr; //用来记录两指针相遇的那个结点
        int node = 1;
        
        while(fast->next != nullptr){
            slow = slow->next;
            fast = fast->next;
            if(fast->next != nullptr) //如果fast->next不为空,继续指向后一个
                fast = fast->next;
            else
                return nullptr;
            
            if(slow == fast){ //两指针相遇,temp指向这个相遇指针,说明存在环路
                temp = slow;
                break;
            }
        }
        
        //找入环结点
        if(temp != nullptr){
            slow = head;
            while(slow != fast){
                slow = slow->next;
                fast = fast->next;
            }
            return slow;
        }
        else return nullptr;
        
    }
};

参考资料:

https://blog.csdn.net/Miss_yuki/article/details/81304107#commentsedit

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值