题目链接:http://www.nowcoder.com/practice/253d2c59ec3e4bc68da16833f79a38e4?rp=3&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
思路:找环的入口结点,那么必须先存在环。判断是否存在环的话,可以用Folder判圈法!
所谓“Floyd判圈法”,就是假设有两个小孩子在一个圆圈跑道上赛跑,同时出发,但其中一个小孩的速度是另一个的两倍,所以跑得快的小孩将“追上”跑得慢的小孩(已经超过n圈了)。当超过的那一刻,可以肯定的是,此时快的小孩已经至少跑了1圈以上了,也就是“经过了一个循环”。于是我们可以根据两个小孩是否会相遇来判断“这条路”是否构成一个圈,因为如果不构成一个圈,是一个无限长的直线的话,这两个孩子就永远不会相遇。
do { k1 = next(n, k1); // 小孩1 k2 = next(n, k2); // 小孩2,第一步 if(k2 > ans) ans = k2; k2 = next(n, k2); // 小孩2,第二步 if(k2 > ans) ans = k2; } while(k1 != k2); // 追上以后才停止
有了这个思路,那么这道题就可以解决了,当有圈的时候在以相遇的结点出发,统计回到这个点走了多少步(n步),即圈的大小(为n),然后再利用快慢指针,先让快指针先走n步,接着慢指针和快指针一起走,当他们相遇的时候就是圈的入口结点;
类似于找链表的倒数第几个点,思路是一样的。
参考:http://blog.csdn.net/u010579068/article/details/48272185
本题的代码:
#include<stdio.h> #include<iostream> using namespace std; struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } }; class Solution { public: bool JudgeList(ListNode *pp,int &n)//判断是否成环 { bool bo=false; ListNode *p,*q,*r; p=new ListNode(NULL); q=new ListNode(NULL); p->next=pp; q->next=pp; while(q->next->next) { p=p->next; q=q->next->next; if(p==q) {r=p;bo=true;break;} } if(!bo) return false; else { // printf("p=====%d\n",p->val); n=1; p=p->next; do{ n++; p=p->next; }while(r!=p); return true; } } ListNode* EntryNodeOfLoop(ListNode* pHead) { if(!pHead||!pHead->next) return NULL; ListNode *p,*q; int n=0; p=new ListNode(NULL); q=new ListNode(NULL); if(JudgeList(pHead,n))//有环 { // printf("%d\n",n); int k=0; p->next=pHead; q->next=pHead; while(p->next) { p=p->next; k++; if(k>n) { q=q->next; } if(p==q) {return q;} } } else return NULL; } ListNode* CreatList(ListNode *pHead,int n,int k) { if(n==0) return NULL; ListNode *p,*q,*r; pHead=new ListNode(NULL); p=pHead; if(k==1) r=pHead; cin>>p->val; int x,i=2; while(i<=n) { cin>>x; q=new ListNode(x); p->next=q; p=q; if(i==k) r=q; i++; } // printf("r===%d\n",r->val); p->next=r; return pHead; } }; int main() { //n表示链表的长度,k表示链表的入口结点; int n,k; Solution so; ListNode *L; cin>>n>>k; L=so.CreatList(L,n,k); ListNode *ans=so.EntryNodeOfLoop(L); printf("%d\n",ans->val); return 0; }