关于链表问题的面试题目 【微软面试100题 第七十七题】
题目要求:
1.给定一个单链表,检测是否有环;
2.判断两个无环单链表是否有交点;
3.给定两个单链表,检测两个链表是否有交点;
4.给定单链表,如果有环的话请返回从头结点进入环的第一个结点;
5.只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点;
6.只给定单链表中某个结点p(非空结点),在p前面插入一个结点。
题目分析:
问题1:
方法1 反转链表:每过一个节点就把该节点的指针反向。当有环的时候,最后指针会定位到链表的头部,如果到最后,都没有再到头部,那说明链表不存在循环。(但是会破换链表)
方法2 快慢指针:快指针pf(f就是fast的缩写)每次移动2个节点,慢指针ps(s为slow的缩写)每次移动1个节点,如果快指针能够追上慢指针,那就说明其中有一个环,否则不存在环。
问题2:
方法1 把其中一条链表尾部指到首部。然后判断另外一条链表是否有环,如果有环,则说明两链表相交。
方法2 找到两个链表的尾结点,进行比较,如果两个尾结点相等则相交;
问题3:
先判断两个链表是否带环;----问题1
i).如果两个都不带环,可以用:判断两个无环单链表是否有交点。----问题2
ii).两个都带环:找到两个入环点r1,r2,环1的入环点为r1,从r1开始遍历一圈,每个结点如r2比较。---问题3
iii).一个带环一个不带环,则肯定不相交。
问题4:
用问题1的方法判断是否有环,再采用下图的方法找入口点。
问题5:
问题6:
和问题5的方法相似,在p结点之后插入一个结点,把该结点的值赋值为p结点的值,p结点的值改为插入结点的值。
代码实现:
问题代码1:
#include <iostream> #include <stack> using namespace std; typedef struct ListNode { struct ListNode *next; int data; }ListNode; void InitList(ListNode **head1); bool HasLoop(ListNode *llist); int main(void) { ListNode *h; InitList(&h); if(HasLoop(h)) cout << "有环" << endl; else cout << "无环" << endl; h = NULL; if(HasLoop(h)) cout << "有环" << endl; else cout << "无环" << endl; return 0; } // ------------ // \|/ /|\ //head:1-->5-->9--> void InitList(ListNode **head) { ListNode *tmp = new ListNode; tmp->data = 1; *head = tmp; tmp = new ListNode; tmp->data = 5; (*head)->next = tmp; ListNode *tmp1 = new ListNode; tmp1->data = 9; tmp1->next = *head; tmp->next = tmp1; } bool HasLoop(ListNode *llist) { ListNode *pf=llist; ListNode *ps=llist; while(true) { if(pf && pf->next) { pf=pf->next->next; } else return false; ps=ps->next; if(ps==pf) { break; } } return true; }
问题代码2:
#include <iostream> #include <stack> using namespace std; typedef struct ListNode { struct ListNode *next; int data; }ListNode; void InitList(ListNode **head1,ListNode **head2); bool IsTwoListHasCommonNode(ListNode *head1,ListNode *head2); int main(void) { ListNode *h1,*h2; InitList(&h1,&h2); if(IsTwoListHasCommonNode(h1,h2)) cout << "相交" << endl; else cout << "不相交" << endl; h2=NULL; if(IsTwoListHasCommonNode(h1,h2)) cout << "相交" << endl; else cout << "不相交" << endl; return 0; } //head1:1-->5-->9-->NULL //head1:5-->9-->NULL void InitList(ListNode **head1,ListNode **head2) { ListNode *tmp = new ListNode; tmp->data = 1; *head1 = tmp; tmp = new ListNode; tmp->data = 5; *head2 = tmp; (*head1)->next = tmp; ListNode *tmp1 = new ListNode; tmp1->data = 9; tmp1->next = NULL; tmp->next = tmp1; } ListNode *GotoLastNode(ListNode *head) { while(head->next) head = head->next; return head; } bool IsTwoListHasCommonNode(ListNode *head1,ListNode *head2) { if(head1==NULL || head2==NULL) return false; ListNode *h1 = GotoLastNode(head1); ListNode *h2 = GotoLastNode(head2); if(h1==h2) return true; else return false; }
问题代码3:
#include <iostream> #include <stack> using namespace std; typedef struct ListNode { struct ListNode *next; int data; }ListNode; void InitList(ListNode **head1,ListNode **head2); bool detect(ListNode *head1, ListNode *head2); int main(void) { ListNode *h1,*h2; InitList(&h1,&h2); if(detect(h1,h2)) cout << "相交" << endl; else cout << "不相交" << endl; h2=NULL; if(detect(h1,h2)) cout << "相交" << endl; else cout << "不相交" << endl; return 0; } //head1:1-->5-->9-->NULL //head1:5-->9-->NULL void InitList(ListNode **head1,ListNode **head2) { ListNode *tmp = new ListNode; tmp->data = 1; *head1 = tmp; tmp = new ListNode; tmp->data = 5; *head2 = tmp; (*head1)->next = tmp; ListNode *tmp1 = new ListNode; tmp1->data = 9; tmp1->next = NULL; tmp->next = tmp1; } ListNode *GotoLastNode(ListNode *head) { while(head->next) head = head->next; return head; } bool HasLoop(ListNode *llist,ListNode **circleNode) { ListNode *pf=llist; ListNode *ps=llist; while(true) { if(pf && pf->next) { pf=pf->next->next; } else return false; ps=ps->next; if(ps==pf) { break; } } //找入环点 ListNode *p=llist; while(p!=ps) { p=p->next; ps=ps->next; } *circleNode = p; return true; } bool detect(ListNode *head1, ListNode *head2) { if(head1==NULL || head2==NULL) return false; ListNode* circleNode1;//链表1的入环点 ListNode* circleNode2;//链表2的入环点 ListNode* lastNode1 = GotoLastNode(head1);//链表1的最后一个结点(无环) ListNode* lastNode2 = GotoLastNode(head2);//链表2的最后一个结点(无环) bool isCircle1 = HasLoop(head1,&circleNode1); bool isCircle2 = HasLoop(head2,&circleNode2); //一个有环,一个无环 if(isCircle1 != isCircle2) return false ; //两个都无环,判断最后一个节点是否相等 else if (!isCircle1 && !isCircle2) { return lastNode1 == lastNode2; } //两个都有环,判断环里的节点是否能到达另一个链表环里的节点 else { ListNode * temp = circleNode1->next; while(temp != circleNode1) { if(temp == circleNode2) return true ; temp = temp->next; } if(temp == circleNode2) return true ; return false ; } return false ; }
问题代码4:
#include <iostream> #include <stack> using namespace std; typedef struct ListNode { struct ListNode *next; int data; }ListNode; void InitList(ListNode **head1); bool HasLoop(ListNode *llist,ListNode **circleNode); int main(void) { ListNode *h1,*circleNode; InitList(&h1); if(HasLoop(h1,&circleNode)) cout << "有环,并且第一个入环点为:" << circleNode->data << endl; else cout << "无环" << endl; return 0; } // _____ // \|/ /|\ //head1:1-->5-->9 void InitList(ListNode **head1) { ListNode *tmp = new ListNode; tmp->data = 1; *head1 = tmp; tmp = new ListNode; tmp->data = 5; (*head1)->next = tmp; ListNode *tmp1 = new ListNode; tmp1->data = 9; tmp1->next = tmp; tmp->next = tmp1; } bool HasLoop(ListNode *llist,ListNode **circleNode) { ListNode *pf=llist; ListNode *ps=llist; while(true) { if(pf && pf->next) { pf=pf->next->next; } else return false; ps=ps->next; if(ps==pf) { break; } } //找入环点 ListNode *p=llist; while(p!=ps) { p=p->next; ps=ps->next; } *circleNode = p; return true; }
很多时候不是我们做不好,而是没有竭尽全力......
posted on 2014-11-23 16:43 tractorman 阅读(1133) 评论(1) 编辑 收藏 举报