【leetcode】第142题 环形链表2(#142. Linked List Cycle II)详解(哈希表+快慢指针),C++

这题的题解中快慢指针法的理解涉及到公式推导,将自己的理解先记下来,防止以后忘记。

题目

在这里插入图片描述在这里插入图片描述

题解1

题解1就是使用 set 作为哈希表,没啥难度,不过需要额外的空间。
思路:
利用 set 容器的唯一性存下每个遍历过的结点,当再次遇到同一结点时该结点即为环的入口,直接返回;若一直到遍历结束也没有相同结点,表示链表无环,返回NULL。
分析: 时间复杂度 O(n),空间复杂度 O(n)
实现:

	ListNode *detectCycle(ListNode *head) {
        set<ListNode*> visited;                         // 已访问过的结点
        while(head){
            if(visited.find(head) != visited.end()){    // 发现重复结点
                return head;
            }else{
                visited.insert(head);
            }
            head = head->next;
        }
        return head;
    }

提交结果:
在这里插入图片描述
提交了好几次,最快就是28ms了,时间应该是消耗在 set 的 find 和 insert 上了。


题解2

思路:
先使用快慢指针,判断链表是否有环;然后重新设置两个指针分别从链表头结点和快慢指针相遇的结点开始,继续遍历结点,当这俩指针相遇时,相遇的结点即为环的入口结点。

详细分析:
若环不存在直接返回 NULL。
若存在环,设 非环结点为 a 个,环内的结点为 b 个,
同时设 快慢指针第一次相遇时快指针已在环内走了 k ∗ b + c k*b + c kb+c ( k = 1 , 2... , 0 ≤ c &lt; b ) ( k = 1,2... ,0 \leq c &lt; b) k=1,2...0c<b(注意,k 最小为 1) 且相遇点距入环处有 b − c b - c bc 个结点的距离。如下图:
在这里插入图片描述
所以,由公式: 2 ∗ 慢 指 针 的 路 程 = 快 指 针 的 路 程 2 * 慢指针的路程 = 快指针的路程 2=, 可得: 2 ∗ ( a + c ) = a + k ∗ b + c 2 * (a + c) = a + k*b + c 2(a+c)=a+kb+c
化简得 a = ( k − 1 ) ∗ b + ( b − c ) a = (k - 1)*b + (b - c) a=(k1)b+(bc)
因此,接下来我们只需要设两个速度相同的指针同时从快慢指针第一次相遇的结点以及链表头结点出发,他们最终会相遇于环入口结点。
时间复杂度 O(n),空间复杂度 O(1) 。

实现:

	ListNode *detectCycle(ListNode *head) {
        if(head == NULL){
            return NULL;
        }
        ListNode* p1 = hasCycle(head);            // 判断是否有环并指向第一次相遇的结点
        if(p1 == NULL){
            return NULL;
        }
        ListNode* p2 = head;                      // 从头开始的指针
        while(p1 != p2){
            p1 = p1->next;
            p2 = p2->next;
        }
        return p1;
    }

    // 使用快慢指针遍历链表,判断是否有环,有则返回快慢指针的相遇结点
    ListNode* hasCycle(ListNode *head){
        ListNode *slow = head;
        ListNode *fast = head;
        while(fast != NULL && fast->next != NULL){  // 若不存在环,快指针会最先到达链表尾部
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast){
                return slow;
            }
        }
        return NULL;
    }

提交结果:
在这里插入图片描述

github源码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值