您的位置:首页 > 职场人生

链表面试汇总

2016-04-12 10:34 323 查看
参考:http://blog.sina.com.cn/s/blog_725dd1010100tqwp.html



http://www.360doc.com/content/15/1122/15/1317564_515001533.shtml

以下都是针对单链表:

1. 给定一个单链表,如何判断是否存在环?

Node* collisionnode=NULL;//碰撞点
bool JudgeCircleExist(Node* head){
if(!head || head->next==0)
return false;
Node *p1=head,*p2=head;
bool result=false;
while(p2 && p2->next){
p1=p1->next;
p2=p2->next->next;
if(p1==p2){
collisionnode=p1;
result=true;
break;
}

}
return result;

}


2. 若存在环,判断是6型环,还是o型环。

答:判断头节点是否在环中

3. 若存在环,则如何知道环的长度?

int Circlelength(Node* head){
JudgeCircleExist(head);
if(!collisionnode)
return 0;
int count=0;
Node *p1=collisionnode, *p2=collisionnode;
while(p2 && p2->next){
++count;
p1=p1->next;
p2=p2->next->next;
if(p1==p2)
break;
}
return count;
}


4. 若存在环,如何找出环的连接点在哪里?

Node* FindLoopPort(Node* head){
JudgeCircleExist(head);
Node *p1=head, *p2=collisionnode,*result=0;
while(p1 && p2){
p1=p1->next;
p2=p2->next;
if(p1==p2){
result=p1;
break;
}
}
return result;

}


5. 带环的单链表的长度是多少?

答:环的长度 + 头节点到连接点的长度

6. 给定两个单链表(head1, head2),检测两个链表是否有交点,如果有返回第一个交点。(第一个公共结点问题)

答:判断是否相交,可通过判断尾节点是否一样

7. 只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。

8. 只给定单链表中某个结点p(非空结点),在p前面插入一个结点。***

void InsertNode_before(Node* p,int x){
Node* node=new Node(p->val);
node->next=p->next;
p->next=node;
p->val=x;
}


9. 给定单链表头结点,删除链表中倒数第k个结点。

10. 链表排序(归并排序)

答:链表排序可用:归并、插入、冒泡及选择(单向链表);归并、快排、插入、冒泡及选择(双向链表);优先考虑归并,时间复杂度低(nlogn),实现简单。

//链表排序1 冒泡  由小到大
Node* Bubble(Node* head){
if(head==NULL)
return 0;
Node *p,*p_pre,*node=head;
int temp;
while(node){
p_pre=head;
p=head->next;
while(p){
if(p_pre->val>p->val){
temp=p_pre->val;
p_pre->val=p->val;
p->val=temp;
}
p_pre=p;
p=p->next;
}
node=node->next;

}
return head;

}
//将链表从中间分开
Node* Middle(Node* head){

Node* p1=head;
Node* p2=head;
Node* mid;
while(p2 &&p2->next){	//注意检查p2->next是否为空
mid=p1;
p1=p1->next;
p2=p2->next->next;
}
mid->next=NULL;
return p1;

}
//将两个有序链表链接成一个新的有序链表
Node* Merge(Node* head1, Node* head2){
Node* p=0;
if(!head1)
return head2;
if(!head2)
return head1;
if(head1->val<head2->val){
p=head1;
p->next=Merge(head1->next,head2);
}
else{

p=head2;
p->next=Merge(head1,head2->next);
}
return p;

}
// 归并排序
Node* mergeSortList(Node* head){
if(!head || !(head->next))
return head;
Node* middle=Middle(head);
Node* first=mergeSortList(head);
Node* second=mergeSortList(middle);
return Merge(first,second);
}


11. 反转单链表(额外的指针记录节点的前驱和后继)

Node* ReverseList(Node* head){
if(!head || !(head->next))
return head;
Node* pre=0,*cur=head,*next=0,*newhead=0;
while(cur){
next=cur->next;
if(next==0)
newhead=cur;
cur->next=pre;
pre=cur;
cur=next;
}
return newhead;
}


12. 两个有序链表的合并

13. 找出链表的中间元素

14. 从尾到头打印单链表

void Print_reverse(Node* head){
if(!head)
return;
Print_reverse(head->next);
cout<<head->val<<' ';
}


15. 0,1,3...,n - 1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里第m个数字。求出这个圆圈里剩下的最后一个数字。(环形链表)

16. 请实现一个函数实现该链表的复制,其中m_pSibling指向的是链表中任意一个结点或者NULL。(复杂链表的复制)

//复杂链表的复制
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {}
};

//链接链表
void f1(RandomListNode* pHead){

if(!pHead)
return;
RandomListNode* node=pHead;
while(node){
RandomListNode* p=new RandomListNode(node->label);
RandomListNode* pnext=node->next;
node->next=p;
p->next=pnext;
node=pnext;
}
}
//设置兄弟指针
void f2(RandomListNode* pHead){

if(!pHead)
return;
RandomListNode* node=pHead;
while(node){
if(!(node->random))
node->next->random=NULL;
else
node->next->random=node->random->next;

node=node->next->next;
}
}
//拆分链表
RandomListNode* f3(RandomListNode* pHead){

if(!pHead)
return 0;
RandomListNode* head=pHead->next;
RandomListNode* node=pHead;
while(node){
RandomListNode* p=node->next;
node->next=p->next;
node=node->next;
if(node) //检查节点是否为空
p->next=node->next;

}
return head;
}

RandomListNode* Clone(RandomListNode* pHead){
f1(pHead);
f2(pHead);
return f3(pHead);
}


17. 删除链表重复元素

Node* DeleteRepeat(Node* head){
if(!head || !(head->next))
return head;
set<int> temp;//遍历链表的时候将不同的元素插入set容器内,以作参考
temp.insert(head->val);
Node* p=head->next;
Node* pre=head;
while(p){

if(temp.find(p->val)!=temp.end()){
pre->next=p->next;
delete p;
p=pre->next;

}
else{
temp.insert(p->val);
pre=p;
p=p->next;

}

}
return head;

}


18. 链表和数组的区别在哪里?

答:数组静态分配内存,链表动态分配内存;数组在内存中连续存放,链表不连续;数组查找元素时间复杂度为O(1),链表查找元素时间复杂度为O(n);数组删除或插入元素时间复杂度为O(n),链表删除或插入元素时间复杂度为O(1);

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: