判断链表是否带环?
用快慢指针法:若带环必然相遇
bool IsExitLoop(ListNode* list)
{
ListNode* fast = list;
ListNode* slow = list;
while (fast && fast->_next)
{
fast = fast->_next->_next;
slow = slow->_next;
if (fast == slow)
{
return true;
}
}
return false;
}
若带环求环的入口点?
假设单链表的总长度为L,头结点到环入口的距离为a,环入口到快慢指针相遇的结点距离为x,环的长度为r,慢指针总共走了s步,则快指针走了2s步。另外,快指针要追上慢指针的话快指针至少要在环里面转了一圈多(假设转了n圈加x的距离),得到以下关系:
s = a + x;
2s = a + nr + x;
=>a + x = nr;
=>a = nr - x;
### 由上式可知:若在头结点和相遇结点分别设一指针,同步(单步)前进,则最后一定相遇在环入口结点,此时返回相遇结点即可
ListNode* FindLoopPort(ListNode* list)
{
ListNode* fast = list;
ListNode* slow = list;
while (fast && fast->_next)
{
fast = fast->_next->_next;
slow = slow->_next;
if (fast == slow) //相遇
{
break;
}
}
slow = list;
while (slow != fast)
{
slow = slow->_next;
fast = fast->_next;
}
return slow;
}
若带环求环的长度?
在环中相遇时,记录相遇结点,单步再走,走到记录的结点处。即走完一圈。。。
int LoopLength(ListNode* list)
{
int size = 0;
ListNode* tmp = FindLoopPort(list);
ListNode* cur = tmp;
while (cur)
{
cur = cur->_next;
size++;
if (cur == tmp)
{
return size;
}
}
}