淘宝的技术笔试题量不大,但是时间也很短(一个小时),基础题的难度还可以,后面的算法编程题就有点难度了,除非是之前做过类似的题目,否则在考场上用极其有限的时间很难做出来。下面和大家分享一道淘宝的编程题。
题目:①判断一个单向链表是否有环,如果有环则找到环的入口节点。
②判断两个单向链表是否相交,如果相交则找到交点节点。
算法思想:①用两个指针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;
- }
转载自:http://blog.csdn.net/piaojun_pj/article/details/5965298