題目:
一個鏈表中包含環,請找出該鏈表的環的入口結點。
思路:
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; } };