持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
一、题目
struct ListNode {
int val;
ListNode *next = nullptr;
inline ListNode(int x, ListNode* next = nullptr) : val(x), next(next) { }
};
bool hasClosedLoop(ListNode* pHead) {
}
int main(int, char**)
{
ListNode p1(3);
ListNode p2(2);
ListNode p3(0);
ListNode p4(-4);
p1.next = &p2;
p2.next = &p3;
p3.next = &p4;
p4.next = &p2;
cout << (hasClosedLoop(&p1) ? "有闭环" : "没有闭环") << endl;
return 0;
}
二、分析
根据题意,要想知道是否有闭环,就得判断是否有后面的节点指向前面的节点。
但是链表没有状态量,如何在遍历的时候判断是否是前面的节点呢?\
假设存在闭环,那在遍历的时候,是永远也到不了尾结点的,而是会回到结环的开头。
假设不存在闭环,在遍历的时候,总是会到尾结点的。
从这个区别考虑,假设在操场上,两个人同时跑步,如果有终点,那跑得快的只会跑一次就能到达终点,如果没有终点,跑得快的肯定会重新回到开头追上另一个人。
既然如此,那我们模拟两个遍历,其中一个快一点,一个慢一点,就能像跑步一样,检测到是否有终点了。
三、模拟
-
创建两个遍历节点
节点一 跑得快A
节点二 跑得慢B -
让两个节点跑起来
跑得快A 等于 跑得快A的下一个节点的下一个节点
跑得慢B 等于 跑得慢B的下一个节点 -
判断跑得快是否追上跑得慢
跑的快A 是否等于 跑得慢B -
迭代
四、实现
bool hasClosedLoop(ListNode* pHead) {
ListNode* rabbit = pHead;
ListNode* tortoise = pHead;
while(rabbit != nullptr && rabbit->next != nullptr){
rabbit = rabbit->next->next;
tortoise = tortoise->next;
if(rabbit == tortoise){
return true;
}
}
return false;
}
五、结言
通过龟兔操场赛跑可以很容易想到这道题的解决办法,在这次的实现中,兔子的速度只是乌龟的两倍,也可以设置快一点,只需要多加一层判空和是否追上即可,程序运行效率也更高。
创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!