欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【小白爬Leetcode141】1.4环形链表 Linked List Cycle

程序员文章站 2022-04-24 12:37:54
...


Leetcode 141 easy\color{#00FF00}{easy}

题目

Description

Given a linked list, determine if it has a cycle in it.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
【小白爬Leetcode141】1.4环形链表 Linked List Cycle
【小白爬Leetcode141】1.4环形链表 Linked List Cycle
【小白爬Leetcode141】1.4环形链表 Linked List Cycle
Follow up:
Can you solve it using O(1) (i.e. constant) memory?

中文描述

给定一个链表,判断链表中是否有环。

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

【小白爬Leetcode141】1.4环形链表 Linked List Cycle
【小白爬Leetcode141】1.4环形链表 Linked List Cycle
【小白爬Leetcode141】1.4环形链表 Linked List Cycle

思路一 暴力解法,空间复杂度O(n)

就是用set记录指针,如果遍历的指针在set里有过了,那肯定是循环了,直接返回这个指针;
如果遇到NULL,肯定是个非循环链表,直接返回跳出循环返回False。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        std::set<ListNode*>node_set;
        while(head)
        {
            if(node_set.find(head)!=node_set.end())
            {
                return true;
            }
            node_set.insert(head);
            head = head->next;
        }
        return false;
    }
};

思路二 快慢指针赛跑

B\color{#FF3030}{这个思路是从B站里看到的}
受到交叉链表思路的影响,其实一开始我也想过两个指针互相追,但是我不知道如何能让两个相遇。看到这个思路,真的感到了降智打击。

**原理很简单:**在一条有限长的环形跑道上,无论跑道有多长,慢的人总能被快的人从身后追上。

第一次尝试,用力过猛:
每一次while循环,慢指针往前走一个,快指针每一步加速一步,越来越快,这样肯定会追上。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast = head;
        int fast_step = 2;
        ListNode* slow = head;
        while(fast && slow)
        {
            slow = slow->next;
            for(int i=0;i<fast_step;i++)
            {
                fast = fast->next;
                if(fast == NULL)
                {return false;}
            }
            if(fast==slow)
            {
                return true;
            }
            fast_step++;
        }
        return false;
    }
};

结果依旧很惨淡,一定有更简单的方法?
【小白爬Leetcode141】1.4环形链表 Linked List Cycle
来到评论区,发现问题出在快指针每一步加速一步。让子弹飞里有句话:步子大了,容易扯着egg,每一个while循环都让fast_step加速很容易让快慢指针一次次擦肩而过。让fast_step==2,slow_step每次为1,那么可以确保第一次二者就能相遇,具体的数学原理如下:
图片来源:leetcode中国站
【小白爬Leetcode141】1.4环形链表 Linked List Cycle
这里直接用leetcode原话。另外注意这里 h(mod C) 的意思是,h是经过对C取余运算后的值。
【小白爬Leetcode141】1.4环形链表 Linked List Cycle
“因此,如果列表是有环的,快指针和慢指针最后会同时指向同一个节点,因此被称为 相遇 。”

综上,直接删掉源代码里的fast_step++;即可。
【小白爬Leetcode141】1.4环形链表 Linked List Cycle

思路三 这也太贱了hhh

秀儿一:
好嘛,原链表全毁了

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        while head:
            if head.val == 'bjfuvth':
                return True
            else:
                head.val = 'bjfuvth'
            head = head.next
        return False

秀儿二:
【小白爬Leetcode141】1.4环形链表 Linked List Cycle

public class Solution {
    public boolean hasCycle(ListNode head) {
        int count=8029;
        
        while(head!=null&&count>0){
            head=head.next;
            count--;
        }
        if(head==null)
            return false;     
        return true; 
    }
}

秀儿三:
这位老哥把链表撕得稀碎,但是比我聪明得多。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
 //新建END节点,将遍历过的节点指向END,如果==END就是有环
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(!head) return false;
        ListNode * END =new ListNode(0);
        ListNode* pre;
        while(head){
            if(head==END) return true;
            pre=head;
            head=head->next;
            pre->next=END;
        }
        return false;
    }
};

怀74.00\color{#FF3030}{我甚至怀疑这些骚操作占据了前74.00。。。}