想了解环形链表的end()的问题,结果不小心瞄到了快慢指针几个大字,那就先按照这个思路写一下吧,第一版:
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode *p, *q;
if (!head)
return false;
p = head;
q = head -> next;
while (p) {
if (p == q)
return true;
if (p -> next == NULL || q -> next == NULL || q -> next -> next == NULL)
return false;
p = p -> next;
q = q -> next -> next;
}
return false;
}
};
参考题解这种思路的写法,会比上面的代码可读性好很多。优化前的问题是:最后的return false是多余的return true也可以通过,因为不写这句会有无返回值的错误,所以加这一句;
这里while的条件设置也不好,while(true)也可以通过;
while内部有两个if语句,满足均可以直接return结束循环。
综上三点,优化代码如下:
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode *p, *q;
if (!head)
return false;
p = head;
q = head -> next;
while (p != q) {
if (p -> next == NULL || q -> next == NULL || q -> next -> next == NULL)
return false;
p = p -> next;
q = q -> next -> next;
}
return true;
}
};
把其中一个if语句提出来作为while的条件,同时最后的return也有了意义。
快慢指针的思路也就是「Floyd 判圈算法」(又称龟兔赛跑算法)。
另一个思路是通过哈希表,若节点未被访问过,insert;若已被访问过count()返回1,return true。题解代码如下:
class Solution {
public:
bool hasCycle(ListNode *head) {
unordered_set<ListNode*> seen;
while (head != nullptr) {
if (seen.count(head)) {
return true;
}
seen.insert(head);
head = head->next;
}
return false;
}
};
回到最开始好奇的end()函数。list::end()是C++ STL中的内置函数,用于使迭代器经过最后一个元素。而list是双向链表,线性结构,不存在有环的情况。