问题1:判断链表是否循环?
解析:
设置1个快指针(每次向前走2个节点),一个慢指针(每次向前走1个节点),如果存在环,则快指针肯定能赶上慢指针;
简单代码:
bool isLoopList(const ListNode* root)
{
if(root == NULL) return false;
const ListNode *pFast = root,*pSlow = root;
while(true)
{
if(pFast->next == NULL) return false;
pFast = pFast->next->next;
pSlow = pSlow->next;
if(pFast == pSlow) return true;
}
}
简单测试:
const int N = 10;
string tmp("A");
ListNode* root = new ListNode;
root->value = tmp;
tmp += 'A';
ListNode* cur = root,*loopNode = NULL;
int i = 0;
while(i <= N)
{
InsertAfter(cur,tmp);
tmp += 'A';
cur = cur->next;
if(i==3)//测试用例,设定循环开始节点为3
loopNode = cur;
++i;
}
cur->next = loopNode;//循环链表
if(isLoopList(root)) cout<<"Loop List.\n";
问题2:找循环单链表的开始循环节点,如A->B->C->D->E->C,则C为开始循环节点。不存在循环则返回NULL;
简单代码:
const Node* LoopStart(const Node* root)
{
if(root==NULL) return NULL;
const Node *slow=root,*fast=root;
while(fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)//相遇节点
break;
}
if(fast->next == NULL) return NULL;
//slow重新到头部节点,slow和fast再次相遇的节点必定是循环开始节点
slow = root;
while(slow != fast)
{
slow = slow->next;
fast = fast->next;
}
return fast;
}
简单测试代码:
const int N = 10;
string tmp("A");
ListNode* root = new ListNode;
root->value = tmp;
tmp += 'A';
ListNode* cur = root,*loopNode = NULL;
int i = 0;
while(i <= N)
{
InsertAfter(cur,tmp);
tmp += 'A';
cur = cur->next;
if(i==3)//测试用例,设定循环开始节点为3
loopNode = cur;
++i;
}
cur->next = loopNode;//循环链表
const ListNode* start = LoopStart(root);
if(start != NULL)
cout<<"Loop Start Node : "<<start->value<<endl;