判断链表是否有环,是个基础性的问题。一般大多数人能想到的是空间复杂度为O(N)的解法,开一个HashSet记录是否被mark过;再劣一点的,可能就时间复杂度为O(N²)的蛮力解法。我们需要一个空间复杂度为O(1),时间复杂度为O(N)的解法,可以用双指针实现。双指针,一定要在碰到链表类算法题的时候,想起它一下,对你有益!
链接:判断链表中是否有环
单链表如果有环,则只可能是下面情况:
下面这种情况是不存在的(由单链表的定义可以知道)
这样,双指针代码就好写了:
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
return true;
}
}
return false;
}
};
在一个环中,快指针和慢指针必定会有重合,这就像一辆跑车和一个人在操场上循环一样,肯定会有许多次相交的点。
推荐给大家一个漫画教程,讲述了快慢指针的一些应用:
漫画算法
这个链接里面还有两道有意思的题目,mark简单分析一下:
第1题:判断两个单向链表是否相交,如果相交,求出交点。
第2题:在一个有环链表中,如何找出链表的入环点?
对于第1题:两个链表有其各自的长度,我们先分别求出来,定义两个快慢指针,让快指针先往前移动(长-短)的差额;接着,快慢指针同步移动,每次都取快慢指针的next,如果相同就找到了交汇点。
对于第2题:
先咕着,明天来写!