链表面试汇总
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. 给定一个单链表,如何判断是否存在环?
2. 若存在环,判断是6型环,还是o型环。
答:判断头节点是否在环中
3. 若存在环,则如何知道环的长度?
4. 若存在环,如何找出环的连接点在哪里?
5. 带环的单链表的长度是多少?
答:环的长度 + 头节点到连接点的长度
6. 给定两个单链表(head1, head2),检测两个链表是否有交点,如果有返回第一个交点。(第一个公共结点问题)
答:判断是否相交,可通过判断尾节点是否一样
7. 只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。
8. 只给定单链表中某个结点p(非空结点),在p前面插入一个结点。***
9. 给定单链表头结点,删除链表中倒数第k个结点。
10. 链表排序(归并排序)
答:链表排序可用:归并、插入、冒泡及选择(单向链表);归并、快排、插入、冒泡及选择(双向链表);优先考虑归并,时间复杂度低(nlogn),实现简单。
11. 反转单链表(额外的指针记录节点的前驱和后继)
12. 两个有序链表的合并
13. 找出链表的中间元素
14. 从尾到头打印单链表
15. 0,1,3...,n - 1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里第m个数字。求出这个圆圈里剩下的最后一个数字。(环形链表)
16. 请实现一个函数实现该链表的复制,其中m_pSibling指向的是链表中任意一个结点或者NULL。(复杂链表的复制)
17. 删除链表重复元素
18. 链表和数组的区别在哪里?
答:数组静态分配内存,链表动态分配内存;数组在内存中连续存放,链表不连续;数组查找元素时间复杂度为O(1),链表查找元素时间复杂度为O(n);数组删除或插入元素时间复杂度为O(n),链表删除或插入元素时间复杂度为O(1);
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);
相关文章推荐
- 剑指offer-面试题40:数组中只出现一次的数字
- 怎么做好一个职业导师
- LeetCode(47)-Reverse Bits
- 面试小结 学习小结
- 为什么每个程序员都应该学习使用命令行
- 面试发现这样的公司太糟心,不能去!
- GitHub 前端工作面试问题
- 跋涉不止(39)
- 蘑菇街电话面试
- Android 面试(完结篇)
- 【风口之下,猪都能飞】(一道算法面试题) (待续)
- 最新iOS面试必看题视频教程(附大神简历要素)
- 程序员必须知道的几个Git代码托管平台
- 数据分析师常见的10道面试题解答
- 求最高分(华为简单面试题)
- 2016-04-10
- 剑指offer面试题 不用加减乘除做加法&&不能被继承的类
- 瞬联科技面试
- java面试题------40个Java集合面试问题和答案
- java面试题------40个Java集合面试问题和答案