zoukankan      html  css  js  c++  java
  • LeetCode 142 环形链表 II

    链接:https://leetcode-cn.com/problems/linked-list-cycle-ii

    给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

    为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

    说明:不允许修改给定的链表。

    示例 :

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

    这道题的解法十分巧妙,只能膜拜。。用到了快慢指针,让快慢指针同时走,但是快指针一次走两步,慢指针一次走一步。可以想象,当慢指针走到出现环的交点时,快指针已经走到环中的某个位置了。假设慢指针走了x步到达交点,那么快指针此时已经走了2x步。假设快指针还要走y步再次到达交点,那么当慢指针从交点出发再走y步时,快慢指针相遇,这是因为快指针的速度是慢指针的2倍。当快慢指针相遇时,让慢指针指向头节点,快指针依然在相遇的位置,这时让快慢指针都是一次走一步,那么当快慢指针再次相遇的时候,就是所求的出现环的交点。这是因为,慢指针从头节点走x步到达交点,和之前一样。而快指针从相遇位置也是再走x步到达交点。

    这道题画个图就很清楚,环的位置其实是求快慢指针再次相遇时所在位置。

    如果不存在环,那么快慢指针不会走到环中去,由于快指针走的快,所以它会一直走到空。当出现空的时候,说明不存在环,函数直接返回空就好。

    c++代码如下:

     1 class Solution {
     2 public:
     3     ListNode *detectCycle(ListNode *head) {
     4         auto slow = head, fast = head;
     5         while(fast){
     6             fast = fast->next;
     7             slow = slow->next;
     8             if(fast){
     9                 fast = fast->next;
    10             }
    11             else break;
    12             
    13             if(fast == slow){
    14                 slow = head;
    15                 while(fast != slow){
    16                     fast = fast->next;
    17                     slow = slow->next;
    18                 }
    19                 return slow;
    20             }
    21         }
    22         return NULL;
    23     }
    24 };

    在写代码的时候,出现了一个bug,看了好久才看出来,错误代码如下:

     1 class Solution {
     2 public:
     3     ListNode *detectCycle(ListNode *head) {
     4         auto slow = head, fast = head;
     5         while(fast){
     6             if(slow != fast){
     7                 slow = slow->next;
     8                 fast = fast->next;
     9                 if(fast){
    10                     fast = fast->next;
    11                 }
    12                 else break;
    13             }
    14             else{
    15                 slow = head;
    16                 while(slow != fast){
    17                     slow = slow->next;
    18                     fast = fast->next;
    19                 }
    20                 return fast;
    21             }  
    22         }
    23         return NULL;
    24     }
    25 };

    思路是一样的,当快慢指针没有相遇的时候,两个指针以不同的速度向前走,直到相遇时让慢指针回到头节点再开始走,直到快慢节点在交点相遇。区别在于第二个代码先判断了快慢指针是否相遇,而在初始化时快慢指针都指向头节点,所以第6行的判断是不成立的,里面的语句并没有执行。还是要多练习,才能避坑呀。

  • 相关阅读:
    APP-SERVICE-SDK:setStorageSync:fail;at page/near/pages/shops/shops page lifeCycleMethod onUnload function
    css 别人找的css特效
    项目笔记2
    Win7如何删除需要管理员权限才能删除的文件夹
    Win7下C:UsersCortana以账户名称命名的系统文件夹用户名的修改
    Win10下C:UsersJohn以账户名称命名的系统文件夹用户名的修改
    windows10企业版怎么关闭自动更新
    给MySQL_5.7 配置环境变量
    用PE安装操作系统时:无法创建新的系统分区 也无法定位现有系统分区 的解决办法
    电脑内存和磁盘空间有什么区别与联系
  • 原文地址:https://www.cnblogs.com/hellosnow/p/11564475.html
Copyright © 2011-2022 走看看