判断一条链表是否是环形链表的两种方法

本文介绍两种检测链表是否为环形的有效方法:哈希表法和快慢指针法。哈希表法通过存储链表节点地址,判断是否有重复节点来确定是否存在环;快慢指针法则利用两个速度不同的指针,若两者相遇则说明链表有环。两种方法的时间复杂度均为O(n),但空间复杂度不同。
摘要由CSDN通过智能技术生成

环形链表的示意图如下
环形链表图
我们假设定义的单链表如下

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

方法一:哈希表法
这里我们采用set这一关联容器。设置set的下标为ListNode*,遍历该链表的每一个结点,将未出现过的链表结点存储至set中,会出现两种情况:

  1. 发现指向某一结点的指针已经存储过了,就说明这个链表是环形的。
  2. 发现指向某一结点的指针是NULL,则说明这条链表有尾巴,不是环形的。
bool IsCycle(ListNode* head){
	set<ListNode*> Node;
	while(head){
		if(Node.find(head)==Node.end()){
			Node.insert(head);//如果未找到,则将该指针存储到set容器中
		}else return true;//如果找到了,则属于第一种情况
		head=head->next;//移动指针指向下一个元素
	}
	return false;//如果跳出循环,则说明head是NULL,属于第二种情况
}

该算法时间复杂度为 O(n),空间复杂度为 O(n)

方法二:快慢指针法
我们可以思考一个问题:两位运动员在环形跑道上什么情况下会相遇?
是当他们速度一致吗?显然不是,应该是当他们有速度差的时候,快的会逐渐追上慢的。
在这里我们只是将运动员换成了指针,将赛道换成了环形链表。
于是有了下面的代码:

bool IsCycle(ListNode* head){
	ListNode *fast, *slow;
	//首先要排除该链表为空或只有一个节点,两种情况均不可能是循环链表
	//排除的其他原因是链表为空时,slow和fast指针均会失效
	//当只有一个节点时,fast则会失效
	if(head==NULL || head->next==NULL) return false;
	fast=head->next;//从起点开始,fast就比slow快一步
	slow=head;
	while(fast!=slow){
		//如果fast或fast->next为空:则该链表不是循环链表
		if(fast==NULL || fast->next==NULL)  return false;
		//在“跑步”过程中,fast每跑两步,slow只跑一步
		fast=fast->next->next;
		slow=slow->next;
	}
	return true;//跳出循环也就意味着fast追上了slow,该链表是循环链表
}

该算法的时间复杂度为 O(n),空间复杂度为 O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

「江太白」

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

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

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

打赏作者

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

抵扣说明:

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

余额充值