单链表有环问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yanerhao/article/details/78069162

面试中单链表有环问题及其变形单链表是否相交是比较常见的问题,这里总结如下

1判断是否有环,引入slow=slow->next慢指针和fast=fast->next->next,这两个指针如果有环则迟早相遇

//是否有环
struct node{int val;node* next;};
bool ishoop(node *h){
node *slow=h;
node *fast=h;
while(fast&&fast->next){
    fast=fast->next->next;
    slow=slow->next;
    if(fast==slow)return 1;
                        }
if(fast==NULL||fast->next==NULL)return 0;//链表数偶数fast,奇数fast->next
}

2 环的长度r,从第一次两个指针开始计数,当第二次再相遇时停止,计数结果即为环的长度

int lenloop(node *h){
if(h==NULL)return 0;
node *slow=h;
node *fast=h;
bool first=0;
bool again=0;
int len=0;
while(fast&&fast->next){
   slow=slow->next;
   fast=fast->next->next;
   if(fast==slow&&again==1){
       break;
                           }//第二次相遇
   if(fast==slow&&again==0){
       first=1;again=1;
                           }//第一次相遇
   if(first)len++;
                        }
return len;
}

3  判断环的入口,当fast与slow相遇时,show肯定没有走完链表,而fast已经在还里走了n(n>= 1)圈。假设slow走了s步,那么fast走了2s步。fast的步数还等于s走的加上环里转的n圈,所以有

2s=s+n*r

设链表起点到入口的长度a,入口长度到相遇点x,则s=a+x,链表总长度L,则相遇点到入口长度为L-a-x

故a+x=n*r=(n-1)*r+r=(n-1)*r+L-a

由此得a=(n-1)*r+L-a-x

这说明:从头结点到入口的距离,等于转了(n-1)圈以后,相遇点到入口的距离。因此,我们可以在链表头、相遇点各设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。

//环入口
node * findentry(node* h){
node *slow=h;
node *fast=h;
while(fast&&fast->next){
    slow=slow->next;
    fast=fast->next->next;
    if(fast==slow)break;
                       }//找到相遇点
if(fast==NULL||fast->next->next==NULL)return NULL;//没有环
slow=h;
while(slow!=fast){
slow=slow->next;
fast=fast->next;
}
return slow;
}
4 .如何判断两个链表(不带环)是否相交?将其中的一个链表首尾相连,然后判断另一个链表是否带环即可。

猜你喜欢

转载自blog.csdn.net/yanerhao/article/details/78069162
今日推荐