环形链表1只要求我们判断链表当中是否有环。 思想 双指针 让快指针一次走慢指针二倍的路程,如果链表当中有环,那么快指针肯定可以追上慢指针,如果相遇 ,那么就有环。
bool hasCycle(struct ListNode *head) {
struct ListNode* slow=head;
struct ListNode* fast=head;
while(fast)
{
fast=fast->next->next;
slow=slow->next;
if(slow==fast)
{return true;
}
}
return false;
}
注意事项
当链表中只要一个节点时是不合法的,应该输出false:
所以应该加一个条件,当没有下一个节点,下下个节点为空时就不进入我们的判断条件:
while(fast&&fast->next&&fast->next->next)
{
fast=fast->next->next;
slow=slow->next;
环形链表II要求我们找到环的起始节点
我们还是先判断是否有环。
如何获得环中节点个数:
获得节点个数之后怎么找到环起始点:
class Solution {
public:
ListNode* MeetingNode(ListNode* head)
{
//判断是否有环
struct ListNode* slow=head;
struct ListNode* fast=head;
while(fast&&fast->next&&fast->next->next)
{
fast=fast->next->next;
slow=slow->next;
if(slow==fast)
{return fast;
}
}
return nullptr;
}
//寻找环的入口
ListNode* startMeetingNode(ListNode* head)
{
//
ListNode* meetingNode=MeetingNode(head);
if(meetingNode==nullptr)return nullptr;
//得到环中节点的数目
int count=1;//计数器
ListNode* PNode1=meetingNode;
while( PNode1->next!=meetingNode)
{
PNode1=PNode1->next;
++count;
}
//找环起始点
//fast先走环中节点个数
PNode1=head;
while(count--)
{
PNode1=PNode1->next;
}
//fast再和slow同步走,相遇即到环入口
ListNode* PNode2=head;
while(PNode1!=PNode2)
{
PNode1=PNode1->next;
PNode2=PNode2->next;
}
return PNode1;
}
ListNode *detectCycle(ListNode *head) {
//判断是否有环
MeetingNode( head);
//找环的入口
return startMeetingNode(head);
}
};
上面代码太冗余了,可以简化为:
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head, *slow = head;
//判断是否有环
while (true) {
if (fast == nullptr || fast->next == nullptr) return nullptr;
fast = fast->next->next;
slow = slow->next;
if (fast == slow) break;
}
//找环入口
fast = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return fast;
}
};