題目:
一個鏈表中包含環,請找出該鏈表的環的入口結點。
思路:
1、哈希表
遍歷整個鏈表,並將鏈表結點存入哈希表中(這里我們使用容器set),如果遍歷到某個鏈表結點已經在set中,那么該點即為環的入口結點;
2、兩個指針
如果鏈表存在環,那么計算出環的長度n,然后准備兩個指針pSlow,pFast,pFast先走n步,然后pSlow和pFase一塊走,當兩者相遇時,即為環的入口處;
3、改進
如果鏈表存在環,我們無需計算環的長度n,只需在相遇時,讓一個指針在相遇點出發,另一個指針在鏈表首部出發,然后兩個指針一次走一步,當它們相遇時,就是環的入口處。(這里就不說明為什么這樣做是正確的,大家可以在紙上推導一下公式)
代碼:
參考在線測試OJ的AC代碼
在線測試OJ:
http://www.nowcoder.com/books/coding-interviews/253d2c59ec3e4bc68da16833f79a38e4?rp=3
AC代碼:
1、哈希表
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead==NULL || pHead->next==NULL)
return NULL;
set<ListNode*> listSet;
while(pHead!=NULL){
if(listSet.find(pHead)==listSet.end()){
listSet.insert(pHead);
pHead=pHead->next;
}
else
return pHead;
}
return NULL;
}
};
2、兩個指針(改進)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead==NULL || pHead->next==NULL)
return NULL;
ListNode* pSlow=pHead;
ListNode* pFast=pHead;
// detect if the linklist is a circle
while(pFast!=NULL && pFast->next!=NULL){
pSlow=pSlow->next;
pFast=pFast->next->next;
if(pSlow==pFast)
break;
}
// if it is a circle
if(pFast!=NULL){
pSlow=pHead;
while(pSlow!=pFast){
pSlow=pSlow->next;;
pFast=pFast->next;
}
}
return pFast;
}
};
