判断链表是否有环以及查找环的入口点——淘宝笔试归来

淘宝的技术笔试题量不大,但是时间也很短(一个小时),基础题的难度还可以,后面的算法编程题就有点难度了,除非是之前做过类似的题目,否则在考场上用极其有限的时间很难做出来。下面和大家分享一道淘宝的编程题。

 

题目:①判断一个单向链表是否有环,如果有环则找到环的入口节点。

          ②判断两个单向链表是否相交,如果相交则找到交点节点。

算法思想:①用两个指针p1,p2同时指向链表的头部,p1一次移动一步,p2一次移动两步,如果最终p1和p2重合则说明链表有环,如果p2走到空指针(链表的结尾)则说明链表无环。如果最终p1和p2重合,使p2重新指向链表的头结点,然后p1和p2同时一次移动一步,当p1和p2再次重合时该节点指针就是环的入口节点指针。

                ②有了第一问的算法基础,应该不难理解第二问。首先将其中一个链表list1首尾相接,变成一个有环链表,如果另一个链表list2和list1相交的话,list2也将成为一个有环链表,并且环的入口节点就是两个链表的交叉节点。如果两个链表不相交,则list2依然是一个无环链表。

      下面是我用C++实现的程序代码,已经在visual C++6.0上运行通过了,程序中有详细的代码注释,这两个小问题在一个main函数中实现。程序代码中的不足之处还请大家多提宝贵意见。

 

TaobaoTest.cpp

 

[cpp:showcolumns]  view plain copy
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. /*节点的类定义*/  
  5. class Node  
  6. {  
  7. public:  
  8.     int data;  
  9.     Node * next;  
  10.     Node(int data)  
  11.     {  
  12.         this->data=data;  
  13.     }  
  14. };  
  15.   
  16. /*链表的类定义*/  
  17. class List  
  18. {  
  19. public:  
  20.     Node * head;//头结点指针  
  21.     Node * tail;//尾结点指针  
  22.   
  23.     /*用一个整形数组作为参数的构造函数*/  
  24.     List(int array[],int length)  
  25.     {  
  26.         head=new Node(array[0]);  
  27.         Node * temp=head;  
  28.         int i;  
  29.         for(i=1;i<length;i++)  
  30.         {  
  31.             temp->next=new Node(array[i]);  
  32.             temp=temp->next;  
  33.         }  
  34.         temp->next=NULL;  
  35.         tail=temp;  
  36.     }  
  37.   
  38.     /*查找指定位置的节点,并返回指向该节点的指针*/  
  39.     Node * FindNode(int index)  
  40.     {  
  41.         Node * temp=head;  
  42.         while(--index)  
  43.             temp=temp->next;  
  44.         return temp;  
  45.     }  
  46. };  
  47.   
  48. /*判断链表是否有环,如果有环则返回环的首结点指针,否则返回NULL值*/  
  49. Node * FindCircle(List list)  
  50. {  
  51.     Node * p1,* p2;  
  52.     p1=list.head;  
  53.     p2=list.head;  
  54.   
  55.     /*判断链表是否有环,当p1=p2时说明链表有环,程序跳出循环。如果p2一直走到链表尽头则说明没有环。*/  
  56.     do  
  57.     {  
  58.         if(p2->next!=NULL&&p2->next->next!=NULL)  
  59.         {  
  60.             p2=p2->next->next;  
  61.             p1=p1->next;  
  62.         }  
  63.         else  
  64.             return NULL;  
  65.     }  
  66.     while(p1!=p2);  
  67.   
  68.     /*求出环的起点节点,并将其返回*/  
  69.     p2=list.head;  
  70.     while(p1!=p2)  
  71.     {  
  72.         p2=p2->next;  
  73.         p1=p1->next;  
  74.     }  
  75.     return p1;  
  76. }  
  77.   
  78. /*判断两个链表是否交叉,如果交叉返回交叉节点,否则返回NULL。*/  
  79. Node * FindCross(List list1,List list2)  
  80. {  
  81.     list1.tail->next=list1.head;//将list1变成有环链表  
  82.   
  83.     Node * p1,* p2;  
  84.     p1=list2.head;  
  85.     p2=list2.head;  
  86.   
  87.     /*判断链表是否有环,当p1=p2时说明链表有环,程序跳出循环。如果p2一直走到链表尽头则说明没有环。*/  
  88.     do  
  89.     {  
  90.         if(p2->next!=NULL&&p2->next->next!=NULL)  
  91.         {  
  92.             p2=p2->next->next;  
  93.             p1=p1->next;  
  94.         }  
  95.         else  
  96.             return NULL;  
  97.     }  
  98.     while(p1!=p2);  
  99.   
  100.     /*求出环的起点节点,并将其返回*/  
  101.     p2=list2.head;  
  102.     while(p1!=p2)  
  103.     {  
  104.         p2=p2->next;  
  105.         p1=p1->next;  
  106.     }  
  107.     return p1;  
  108. }  
  109.   
  110. int main()  
  111. {  
  112.     /*构造一个有环链表,并查找环的起始节点*/  
  113.     int array[8]={1,2,3,4,5,6,7,8};  
  114.     List list(array,sizeof(array1)/sizeof(int));//构造一个链表  
  115.     list.tail->next=list.FindNode(5);//将该链表构造成一个有环链表  
  116.     Node * temp=FindCircle(list);//查找环的起始节点  
  117.     if(temp==NULL)  
  118.         cout<<"No cirle exists in the list."<<endl;  
  119.     else  
  120.         cout<<"There is a circle in the list , and the value of the join_point is "<<temp->data<<endl;  
  121.   
  122.     /*构造两个链表,然后使这两个链表交叉。最后查找交叉节点。*/  
  123.     int array1[8]={1,2,3,4,5,6,7,8};  
  124.     int array2[5]={9,10,11,12,13};  
  125.     List list1(array1,sizeof(array1)/sizeof(int));//构造链表list1  
  126.     List list2(array2,sizeof(array2)/sizeof(int));//构造链表list2  
  127.     list2.tail->next=list.FindNode(3);//使这两个链表交叉  
  128.     temp=FindCross(list,list2);//查找这两个链表的交叉节点  
  129.     if(temp==NULL)  
  130.         cout<<"These two lists dose not cross."<<endl;  
  131.     else  
  132.         cout<<"These two lists cross with each other , and the value of the corss_point is "<<temp->data<<endl;  
  133.     return 0;  
  134. }  
 

转载自:http://blog.csdn.net/piaojun_pj/article/details/5965298

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值