您的位置:首页 > 其它

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

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

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

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

算法思想:①用两个指针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

#include <iostream>
using namespace std;

/*节点的类定义*/
class Node
{
public:
int data;
Node * next;
Node(int data)
{
this->data=data;
}
};

/*链表的类定义*/
class List
{
public:
Node * head;//头结点指针
Node * tail;//尾结点指针

/*用一个整形数组作为参数的构造函数*/
List(int array[],int length)
{
head=new Node(array[0]);
Node * temp=head;
int i;
for(i=1;i<length;i++)
{
temp->next=new Node(array[i]);
temp=temp->next;
}
temp->next=NULL;
tail=temp;
}

/*查找指定位置的节点,并返回指向该节点的指针*/
Node * FindNode(int index)
{
Node * temp=head;
while(--index)
temp=temp->next;
return temp;
}
};

/*判断链表是否有环,如果有环则返回环的首结点指针,否则返回NULL值*/
Node * FindCircle(List list)
{
Node * p1,* p2;
p1=list.head;
p2=list.head;

/*判断链表是否有环,当p1=p2时说明链表有环,程序跳出循环。如果p2一直走到链表尽头则说明没有环。*/
do
{
if(p2->next!=NULL&&p2->next->next!=NULL)
{
p2=p2->next->next;
p1=p1->next;
}
else
return NULL;
}
while(p1!=p2);

/*求出环的起点节点,并将其返回*/
p2=list.head;
while(p1!=p2)
{
p2=p2->next;
p1=p1->next;
}
return p1;
}

/*判断两个链表是否交叉,如果交叉返回交叉节点,否则返回NULL。*/
Node * FindCross(List list1,List list2)
{
list1.tail->next=list1.head;//将list1变成有环链表

Node * p1,* p2;
p1=list2.head;
p2=list2.head;

/*判断链表是否有环,当p1=p2时说明链表有环,程序跳出循环。如果p2一直走到链表尽头则说明没有环。*/
do
{
if(p2->next!=NULL&&p2->next->next!=NULL)
{
p2=p2->next->next;
p1=p1->next;
}
else
return NULL;
}
while(p1!=p2);

/*求出环的起点节点,并将其返回*/
p2=list2.head;
while(p1!=p2)
{
p2=p2->next;
p1=p1->next;
}
return p1;
}

int main()
{
/*构造一个有环链表,并查找环的起始节点*/
int array[8]={1,2,3,4,5,6,7,8};
List list(array,sizeof(array1)/sizeof(int));//构造一个链表
list.tail->next=list.FindNode(5);//将该链表构造成一个有环链表
Node * temp=FindCircle(list);//查找环的起始节点
if(temp==NULL)
cout<<"No cirle exists in the list."<<endl;
else
cout<<"There is a circle in the list , and the value of the join_point is "<<temp->data<<endl;

/*构造两个链表,然后使这两个链表交叉。最后查找交叉节点。*/
int array1[8]={1,2,3,4,5,6,7,8};
int array2[5]={9,10,11,12,13};
List list1(array1,sizeof(array1)/sizeof(int));//构造链表list1
List list2(array2,sizeof(array2)/sizeof(int));//构造链表list2
list2.tail->next=list.FindNode(3);//使这两个链表交叉
temp=FindCross(list,list2);//查找这两个链表的交叉节点
if(temp==NULL)
cout<<"These two lists dose not cross."<<endl;
else
cout<<"These two lists cross with each other , and the value of the corss_point is "<<temp->data<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: