牛客BM6 判断链表中是否有环

这篇博客介绍了如何在链表中检测环的存在,提供了三种解法:1) 使用哈希表(set 或 map)记录节点;2) 应用快慢双指针技巧;3) 通过循环次数判断。重点讨论了哈希表和双指针方法,这两种方法在时间复杂度上均为O(n),空间复杂度分别为O(n)和O(1)。
摘要由CSDN通过智能技术生成

描述

判断给定的链表中是否有环。如果有否则返回true,否则返回false。

数据范围:链表长度 0≤n≤10000,链表中任意节点的值满足 ∣val∣<=100000

要求:空间复杂度 O(1),时间复杂度 O(n)。

例如输入{3,2,0,-4}时,对应的链表结构如下图所示:

 可以看出环的入口结点为从头结点开始的第1个结点(注:头结点为第0个结点),所以输出true。

结构体初始定义如下:

struct ListNode {
     int val;
     ListNode *next;
     ListNode(int x) : val(x), next(NULL) {}
 };

解法一 哈希表

1.set哈希表

class Solution
{
public:
    bool hasCycle(ListNode *head)
    {
        set<ListNode*> s;
        while(head!=NULL)
        {
            if(s.find(head)!=s.end())
                return true;
            else
                s.insert(head);
            head=head->next;        
        } 
        return false;
    }
};

2.map哈希表

class Solution
{
public:
    bool hasCycle(ListNode *head)
    {
        map<ListNode*,bool> m;
        while(head!=NULL)
        {
            if(m.find(head)!=m.end())
                return true;
            else
                m[head]=true;//添加键值
            head=head->next;        
        } 
        return false;
    }
};

以上两种方法在本质上是一样的。都是利用哈希表来判断链表中是否有环。

解法二 快慢双指针

      使用两个指针,fast和slow,他们起始的位置都是链表头部,随后,slow指针每次向后移动一个位置,而fast每次向后移动两个位置,如果链表中存在环,那么这两个指针最终会再次相遇。

class Solution
{ 
public:
    bool hasCycle(ListNode* head)
    {
        ListNode *slow = head, *fast = head;
        while ( fast && fast->next) 
        {
            slow = slow->next;
            fast = fast->next->next;
            
            if (slow == fast)
                return true;
        }
        
            return false;
    }
};

解法三 灵魂解法。。(不推荐)

题目中说了n的范围是0到10000,所以如果循环次数大于10000是不是说明一定有环,反之如果循环到一定次数结束了说明一定无环...

class Solution {
public:
    bool hasCycle(ListNode *head) {
        int sum=0;//题目中说了n的范围是0到10000,所以如果循环次数大于10000是不是说明一定有环,反之如果循环到一定次数结束了说明一定无环
        while(head)
        {
            head=head->next;
            sum++;
            if(sum>10000)
                return true;
        }
        return false;
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dorakmon0219

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值