😈博客主页:🐼大家好我叫张同学🐼
💖 欢迎点赞 👍 收藏 💗留言 📝 欢迎讨论! 👀
🎵本文由 【大家好我叫张同学】 原创,首发于 CSDN 🌟🌟🌟
✨精品专栏(不定时更新) 【数据结构+算法】 【做题笔记】【C语言编程学习】
☀️ 精品文章推荐
【C语言进阶学习笔记】三、字符串函数详解(1)(爆肝吐血整理,建议收藏!!!)
【C语言基础学习笔记】+【C语言进阶学习笔记】总结篇(坚持才有收获!)
前言 |
题目内容 |
原题链接(点击跳转)
暴力取巧法 |
要解决这个问题,有一个不算方法的方法,我们注意到题目中说了链表中节点的数目范围是[0, 10^4]
。
对于带环的链表,我们去求其长度,一定是大于10^4
的(也就是10000
)。
对于不带环的链表,其长度一定是小于等于10000
的。因此这个地方可以取巧,直接取计算链表的长度,就可以判断是否带环。
函数实现 |
bool hasCycle(struct ListNode *head) {
//暴力求解法 如果链表有环,长度计算length会无穷大
struct ListNode* cur = head;
int length = 0;
while(cur && (length < 100001)) {
cur = cur->next;
length++;
}
if(cur == NULL)
return false;
else
return true;
}
虽然这种方法可以求出链表是否带环,但实际中我们最好不要使用
这种方法。
原因如下:
快慢指针法 |
要判断链表是否带环,一般都采用快慢指针
的方法(快指针
一次走两步
,慢指针
一次走一步
)。若链表不带环,那么快指针
势必会走到最后一个结点或空结点,即fast = NULL
,或 fast->next = NULL
。若链表不带环,那么快指针后面就会一直在环里面走啊走,转啊转,出不去。若while
循环中终止条件是fast == NULL
或 fast->next == NULL
,那么while
循环就无法终止。为了在链表带环时,while
循环还能终止,将条件改为 fast != slow
。若带环,则fast
与slow
必定会在环中相遇。(证明过程在后面)
函数实现 |
bool hasCycle(struct ListNode *head) {
if(head == NULL || head->next == NULL)
return false;
struct ListNode* fast = head->next;
struct ListNode* slow = head;
while(fast != slow){
if(fast == NULL || fast->next == NULL)
return false;
fast = fast->next->next;
slow = slow->next;
}
return true;
}
当然也可以这样写,这样就不需要利用虚拟结点,fas
t和slow
同时从头结点head
开始往后走。
bool hasCycle(struct ListNode *head) {
struct ListNode *fast = head,*slow = head;
while(fast && fast->next){
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
return true;
}
return false;
}
带环问题的证明过程 |
问题(1)
答:一定可以追上,证明如下:
问题(2)
答:不一定可以追上,证明如下: