编程之美--编程判断两个链表是否相交
2012-03-31 20:21
417 查看
输入一个单向链表,输出该链表中倒数第k个结点,
链表的倒数第0个结点为链表的尾指针。
相信,稍微有点 经验的同志,都会说到:设置两个指针p1,p2,首先p1和p2都指向head,然后p2向前走k步,这样p1和p2之间就间隔k个节点,最后p1和p2同时向前移动,直至p2走到链表末尾。
这是针对链表单项链表查找其中倒数第k个结点。试问,如果链表是双向的,且可能存在环呢?编程判断两个链表是否相交。
给出两个单向链表的头指针(如下图所示),
比如h1、h2,判断这两个链表是否相交。这里为了简化问题,我们假设两个链表均不带环。
编程之美的解析:
直接循环判断第一个链表的每个节点是否在第二个链表中。但,这种方法的时间复杂度为O(Length(h1) * Length(h2))。显然,我们得找到一种更为有效的方法,至少不能是O(N^2)的复杂度。
针对第一个链表直接构造hash表,然后查询hash表,判断第二个链表的每个结点是否在hash表出现,如果所有的第二个链表的结点都能在hash表中找到,即说明第二个链表与第一个链表有相同的结点。时间复杂度为为线性:O(Length(h1) + Length(h2)),同时为了存储第一个链表的所有节点,空间复杂度为O(Length(h1))。是否还有更好的方法呢,既能够以线性时间复杂度解决问题,又能减少存储空间?
进一步考虑“如果两个没有环的链表相交于某一节点,那么在这个节点之后的所有节点都是两个链表共有的”这个特点,我们可以知道,如果它们相交,则最后一个节点一定是共有的。而我们很容易能得到链表的最后一个节点,所以这成了我们简化解法的一个主要突破口。那么,我们只要判断俩个链表的尾指针是否相等。相等,则链表相交;否则,链表不相交,O((Length(h1) + Length(h2))
上面的问题都是针对链表无环的,那么如果现在,链表是有环的呢?还能找到最后一个结点进行判断么?上面的方法还同样有效么?显然,这个问题的本质已经转化为判断链表是否有环。那么,如何来判断链表是否有环呢?
所以,事实上,这个判断两个链表是否相交的问题就转化成了:
1.先判断带不带环
2.如果都不带环,就判断尾节点是否相等
3.如果都带环,判断一链表上俩指针相遇的那个节点,在不在另一条链表上。
如果在,则相交,如果不在,则不相交。
如何编写代码来判断链表是否有环呢?因为很多的时候,你给出了问题的思路后,面试官可能还要追加你的代码,ok,如下(设置两个指针(p1,
p2),初始值都指向头,p1每次前进一步,p2每次前进二步,如果链表存在环,则p2先进入环,p1后进入环,两个指针在环中走动,必定相遇):
如果都不带环,就判断尾节点是否相等,如果都带环,判断一链表上俩指针相遇的那个节点,在不在另一条链表上。下面是综合解决这个问题的代码:
链表的倒数第0个结点为链表的尾指针。
相信,稍微有点 经验的同志,都会说到:设置两个指针p1,p2,首先p1和p2都指向head,然后p2向前走k步,这样p1和p2之间就间隔k个节点,最后p1和p2同时向前移动,直至p2走到链表末尾。
struct ListNode { char data; ListNode* next; }; ListNode* head,*p,*q; ListNode *pone,*ptwo; ListNode* fun(ListNode *head,int k) { assert(k >= 0); pone = ptwo = head; for( ; k > 0 && ptwo != NULL; k--) ptwo=ptwo->next; if (k > 0) return NULL; while(ptwo!=NULL) { pone=pone->next; ptwo=ptwo->next; } return pone; } |
给出两个单向链表的头指针(如下图所示),
比如h1、h2,判断这两个链表是否相交。这里为了简化问题,我们假设两个链表均不带环。
编程之美的解析:
直接循环判断第一个链表的每个节点是否在第二个链表中。但,这种方法的时间复杂度为O(Length(h1) * Length(h2))。显然,我们得找到一种更为有效的方法,至少不能是O(N^2)的复杂度。
针对第一个链表直接构造hash表,然后查询hash表,判断第二个链表的每个结点是否在hash表出现,如果所有的第二个链表的结点都能在hash表中找到,即说明第二个链表与第一个链表有相同的结点。时间复杂度为为线性:O(Length(h1) + Length(h2)),同时为了存储第一个链表的所有节点,空间复杂度为O(Length(h1))。是否还有更好的方法呢,既能够以线性时间复杂度解决问题,又能减少存储空间?
进一步考虑“如果两个没有环的链表相交于某一节点,那么在这个节点之后的所有节点都是两个链表共有的”这个特点,我们可以知道,如果它们相交,则最后一个节点一定是共有的。而我们很容易能得到链表的最后一个节点,所以这成了我们简化解法的一个主要突破口。那么,我们只要判断俩个链表的尾指针是否相等。相等,则链表相交;否则,链表不相交,O((Length(h1) + Length(h2))
上面的问题都是针对链表无环的,那么如果现在,链表是有环的呢?还能找到最后一个结点进行判断么?上面的方法还同样有效么?显然,这个问题的本质已经转化为判断链表是否有环。那么,如何来判断链表是否有环呢?
所以,事实上,这个判断两个链表是否相交的问题就转化成了:
1.先判断带不带环
2.如果都不带环,就判断尾节点是否相等
3.如果都带环,判断一链表上俩指针相遇的那个节点,在不在另一条链表上。
如果在,则相交,如果不在,则不相交。
如何编写代码来判断链表是否有环呢?因为很多的时候,你给出了问题的思路后,面试官可能还要追加你的代码,ok,如下(设置两个指针(p1,
p2),初始值都指向头,p1每次前进一步,p2每次前进二步,如果链表存在环,则p2先进入环,p1后进入环,两个指针在环中走动,必定相遇):
1. //copyright@ KurtWang 2. //July、2011.05.27。 3. struct Node 4. { 5. int value; 6. Node * next; 7. }; 8. 9. //1.先判断带不带环 10. //判断是否有环,返回bool,如果有环,返回环里的节点 11. //思路:用两个指针,一个指针步长为1,一个指针步长为2,判断链表是否有环 12. bool isCircle(Node * head, Node *& circleNode, Node *& lastNode) 13. { 14. Node * fast = head->next; 15. Node * slow = head; 16. while(fast != slow && fast && slow) 17. { 18. if(fast->next != NULL) 19. fast = fast->next; 20. 21. if(fast->next == NULL) 22. lastNode = fast; 23. if(slow->next == NULL) 24. lastNode = slow; 25. 26. fast = fast->next; 27. slow = slow->next; 28. 29. } 30. if(fast == slow && fast && slow) 31. { 32. circleNode = fast; 33. return true; 34. } 35. else 36. return false; 37. } |
1. //判断带环不带环时链表是否相交 2. //2.如果都不带环,就判断尾节点是否相等 3. //3.如果都带环,判断一链表上俩指针相遇的那个节点,在不在另一条链表上。 4. bool detect(Node * head1, Node * head2) 5. { 6. Node * circleNode1; 7. Node * circleNode2; 8. Node * lastNode1; 9. Node * lastNode2; 10. 11. bool isCircle1 = isCircle(head1,circleNode1, lastNode1); 12. bool isCircle2 = isCircle(head2,circleNode2, lastNode2); 13. 14. //一个有环,一个无环 15. if(isCircle1 != isCircle2) 16. return false; 17. //两个都无环,判断最后一个节点是否相等 18. else if(!isCircle1 && !isCircle2) 19. { 20. return lastNode1 == lastNode2; 21. } 22. //两个都有环,判断环里的节点是否能到达另一个链表环里的节点 23. else 24. { 25. Node * temp = circleNode1->next; //updated,多谢苍狼 and hyy。 26. while(temp != circleNode1) 27. { 28. if(temp == circleNode2) 29. return true; 30. temp = temp->next; 31. } 32. return false; 33. } 34. 35. return false; 36. } |
相关文章推荐
- 读书笔记之编程之美 - 3.6 编程判断两个链表是否相交
- 编程之美3.6——编程判断两个链表是否相交
- 编程之美:编程判断两个链表是否相交
- 编程判断两个链表是否相交
- 编程之美-判断两个链表是否相交 (涵其扩展问题)
- 判断两个链表是否相交(在线编程测试平台www.anycodex.com)
- 编程之美-判断两个链表是否相交
- 3.6 编程判断两个链表是否相交
- 编程判断两个链表是否相交
- 编程之美-编程判断两个链表(可能含环)是否相交以及相交的第一个结点
- 单链表之编程判断两个链表是否相交
- 编程之美-判断两个链表是否相交方法整理
- 3.6 编程判断两个链表是否相交
- 编程之美--3.6编程判断两个链表是否相交
- [编程之美] PSet3.6 编程判断两个链表是否相交
- 《编程之美》——编程判断两个链表是否相交
- 编程之美-3.6-编程判断两个链表是否相交
- 编程之美-3.6-编程判断两个链表是否相交
- 编程判断两个链表是否相交
- 编程之美-3.6-编程判断两个链表是否相交