【左神算法课】超经典:求两单向链表交点(6种情…
2018-06-17 22:01:30来源:未知 阅读 ()
目录
题目描述
思路
程序(C++版&java版)
详解
题目描述:
思路:
这道题实在是太经典,一道题里面考察了几个知识点:
1.链表是否有环的判断
2.链表若有环,要找到环的入口节点
3.两个链表的多种情况分析
另外,左老师讲得实在是太赞了.
程序(详解在后面):
1 //C++版,重写了左老师的Java版 2 #include <iostream> 3 using namespace std; 4 5 //definition for singly-linked list. 6 struct ListNode 7 { 8 int val; 9 ListNode* next; 10 ListNode(int x) : val(x), next(NULL) {} 11 }; 12 13 ListNode* getLoopNode(ListNode* head) { 14 if (NULL == head || NULL == head->next || NULL == head->next->next) 15 return NULL; 16 ListNode* pSlow = head->next; 17 ListNode* pFast = head->next->next; 18 while (pSlow != pFast) { 19 if (NULL == pFast->next || NULL == pFast->next->next) { 20 return NULL; 21 } 22 pSlow = pSlow->next; 23 pFast = pFast->next->next; 24 } 25 pFast = head; //walk again to head,and speed equal.Or pSlow 26 while (pSlow != pFast) { 27 pSlow = pSlow->next; 28 pFast = pFast->next; 29 } 30 return pSlow;//Or pFast 31 } 32 33 ListNode* noLoop(ListNode* head1, ListNode* head2) { 34 if (NULL == head1 || NULL == head2) { 35 return NULL; 36 } 37 ListNode* cur1 = head1; 38 ListNode* cur2 = head2; 39 int n = 0; 40 while (NULL != cur1->next) { 41 ++n; 42 cur1 = cur1->next; 43 } 44 while (NULL != cur2->next) { 45 --n; 46 cur2 = cur2->next; 47 } 48 if (cur1 != cur2) { //tail node 49 return NULL; 50 } 51 cur1 = n > 0 ? head1 : head2; 52 cur2 = cur1 == head1 ? head2 : head1; 53 n = abs(n); 54 while (n--) { 55 cur1 = cur1->next; 56 } 57 while (cur1 != cur2) { 58 cur1 = cur1->next; 59 cur2 = cur2->next; 60 } 61 return cur1;//Or cur2 62 } 63 64 ListNode* bothLoop(ListNode* head1, ListNode*loop1, ListNode* head2, ListNode*loop2) { 65 ListNode* cur1 = NULL; 66 ListNode* cur2 = NULL; 67 if (loop1 == loop2) { 68 cur1 = head1; 69 cur2 = head2; 70 int n = 0; 71 while (cur1 != loop1) { 72 ++n; 73 cur1 = cur1->next; 74 } 75 while (cur2 != loop2) { 76 --n; 77 cur2 = cur2->next; 78 } 79 cur1 = n > 0 ? head1 : head2; 80 cur2 = cur1 == head1 ? head2 : head1; 81 n = abs(n); 82 while (n--) { 83 cur1 = cur1->next; 84 } 85 while (cur1 != cur2) { 86 cur1 = cur1->next; 87 cur2 = cur2->next; 88 } 89 return cur1;//Or cur2 90 } 91 else { 92 cur1 = loop1->next; 93 while (cur1 != loop1) { 94 if (cur1 == loop2) { 95 return loop1; 96 } 97 cur1 = cur1->next; 98 } 99 return NULL; 100 } 101 } 102 103 ListNode* getIntersectNode(ListNode* head1, ListNode* head2) { 104 if (NULL == head1 || NULL == head2) 105 return NULL; 106 ListNode* loop1 = getLoopNode(head1); 107 ListNode* loop2 = getLoopNode(head2); 108 if (NULL == loop1 && NULL == loop2) 109 return noLoop(head1, head2); 110 if (NULL != loop1 && NULL != loop2) 111 return bothLoop(head1, loop1, head2, loop2); 112 return NULL;//one of them have loop,so have no intersectionNode 113 } 114 115 int main() { 116 // 1->2->3->4->5->6->7->null 117 ListNode* head1 = new ListNode(1); 118 head1->next = new ListNode(2); 119 head1->next->next = new ListNode(3); 120 head1->next->next->next = new ListNode(4); 121 head1->next->next->next->next = new ListNode(5); 122 head1->next->next->next->next->next = new ListNode(6); 123 head1->next->next->next->next->next->next = new ListNode(7); 124 125 // 0->9->8->6->7->null 126 ListNode* head2 = new ListNode(0); 127 head2->next = new ListNode(9); 128 head2->next->next = new ListNode(8); 129 head2->next->next->next = head1->next->next->next->next->next; // 8->6 130 cout << getIntersectNode(head1, head2)->val << endl; 131 132 133 // 1->2->3->4->5->6->7->4... 134 head1 = new ListNode(1); 135 head1->next = new ListNode(2); 136 head1->next->next = new ListNode(3); 137 head1->next->next->next = new ListNode(4); 138 head1->next->next->next->next = new ListNode(5); 139 head1->next->next->next->next->next = new ListNode(6); 140 head1->next->next->next->next->next->next = new ListNode(7); 141 head1->next->next->next->next->next->next->next = head1->next->next->next;// 7->4 142 143 // 0->9->8->2... 144 head2 = new ListNode(0); 145 head2->next = new ListNode(9); 146 head2->next->next = new ListNode(8); 147 head2->next->next->next = head1->next; // 8->2 148 cout << getIntersectNode(head1, head2)->val << endl; 149 150 // 0->9->8->6->4->5->6... 151 head2 = new ListNode(0); 152 head2->next = new ListNode(9); 153 head2->next->next = new ListNode(8); 154 head2->next->next->next = head1->next->next->next->next->next; // 8->6 155 cout << getIntersectNode(head1, head2)->val << endl; 156 157 return 0; 158 }
1 //Java版.左老师给出的代码,很赞 2 //package problems_2017_08_16; 3 4 public class Problem_03_FindFirstIntersectNode { 5 6 public static class Node { 7 public int value; 8 public Node next; 9 10 public Node(int data) { 11 this.value = data; 12 } 13 } 14 15 public static Node getIntersectNode(Node head1, Node head2) { 16 if (head1 == null || head2 == null) { 17 return null; 18 } 19 Node loop1 = getLoopNode(head1); 20 Node loop2 = getLoopNode(head2); 21 if (loop1 == null && loop2 == null) { 22 return noLoop(head1, head2); 23 } 24 if (loop1 != null && loop2 != null) { 25 return bothLoop(head1, loop1, head2, loop2); 26 } 27 return null; 28 } 29 30 public static Node getLoopNode(Node head) { 31 if (head == null || head.next == null || head.next.next == null) { 32 return null; 33 } 34 Node n1 = head.next; // n1 -> slow 35 Node n2 = head.next.next; // n2 -> fast 36 while (n1 != n2) { 37 if (n2.next == null || n2.next.next == null) { 38 return null; 39 } 40 n2 = n2.next.next; 41 n1 = n1.next; 42 } 43 n2 = head; // n2 -> walk again from head 44 while (n1 != n2) { 45 n1 = n1.next; 46 n2 = n2.next; 47 } 48 return n1; 49 } 50 51 public static Node noLoop(Node head1, Node head2) { 52 if (head1 == null || head2 == null) { 53 return null; 54 } 55 Node cur1 = head1; 56 Node cur2 = head2; 57 int n = 0; 58 while (cur1.next != null) { 59 n++; 60 cur1 = cur1.next; 61 } 62 while (cur2.next != null) { 63 n--; 64 cur2 = cur2.next; 65 } 66 if (cur1 != cur2) { 67 return null; 68 } 69 cur1 = n > 0 ? head1 : head2; 70 cur2 = cur1 == head1 ? head2 : head1; 71 n = Math.abs(n); 72 while (n != 0) { 73 n--; 74 cur1 = cur1.next; 75 } 76 while (cur1 != cur2) { 77 cur1 = cur1.next; 78 cur2 = cur2.next; 79 } 80 return cur1; 81 } 82 83 public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) { 84 Node cur1 = null; 85 Node cur2 = null; 86 if (loop1 == loop2) { 87 cur1 = head1; 88 cur2 = head2; 89 int n = 0; 90 while (cur1 != loop1) { 91 n++; 92 cur1 = cur1.next; 93 } 94 while (cur2 != loop2) { 95 n--; 96 cur2 = cur2.next; 97 } 98 cur1 = n > 0 ? head1 : head2; 99 cur2 = cur1 == head1 ? head2 : head1; 100 n = Math.abs(n); 101 while (n != 0) { 102 n--; 103 cur1 = cur1.next; 104 } 105 while (cur1 != cur2) { 106 cur1 = cur1.next; 107 cur2 = cur2.next; 108 } 109 return cur1; 110 } else { 111 cur1 = loop1.next; 112 while (cur1 != loop1) { 113 if (cur1 == loop2) { 114 return loop1; 115 } 116 cur1 = cur1.next; 117 } 118 return null; 119 } 120 } 121 122 public static void main(String[] args) { 123 // 1->2->3->4->5->6->7->null 124 Node head1 = new Node(1); 125 head1.next = new Node(2); 126 head1.next.next = new Node(3); 127 head1.next.next.next = new Node(4); 128 head1.next.next.next.next = new Node(5); 129 head1.next.next.next.next.next = new Node(6); 130 head1.next.next.next.next.next.next = new Node(7); 131 132 // 0->9->8->6->7->null 133 Node head2 = new Node(0); 134 head2.next = new Node(9); 135 head2.next.next = new Node(8); 136 head2.next.next.next = head1.next.next.next.next.next; // 8->6 137 System.out.println(getIntersectNode(head1, head2).value);//output:6 138 139 // 1->2->3->4->5->6->7->4... 140 head1 = new Node(1); 141 head1.next = new Node(2); 142 head1.next.next = new Node(3); 143 head1.next.next.next = new Node(4); 144 head1.next.next.next.next = new Node(5); 145 head1.next.next.next.next.next = new Node(6); 146 head1.next.next.next.next.next.next = new Node(7); 147 head1.next.next.next.next.next.next.next = head1.next.next.next; // 7->4 148 149 // 0->9->8->2... 150 head2 = new Node(0); 151 head2.next = new Node(9); 152 head2.next.next = new Node(8); 153 head2.next.next.next = head1.next; // 8->2 154 System.out.println(getIntersectNode(head1, head2).value);//output:2 155 156 // 0->9->8->6->4->5->6.. 157 head2 = new Node(0); 158 head2.next = new Node(9); 159 head2.next.next = new Node(8); 160 head2.next.next.next = head1.next.next.next.next.next; // 8->6 161 System.out.println(getIntersectNode(head1, head2).value);//output:4 162 System.out.println(getIntersectNode(head2, head1).value);//note the order //output:6 163 164 } 165 166 }
详解
先把几种情况罗列一下:
然后照着程序执行流程梳理思路:
0.判断两链表是否有环(分别找环入口结点,能找到则有环,否则无环):
若都无环,转入第1步(可能是情况1或2);
若都有环,转入第2步(可能是情况4或5或6);
若一个有环一个无环,直接返回NULL,因为如果他们相交,是不可能一个有环一个无环的(图中情况3);
1.都无环的情况,退化到两个无环链表找入口点的问题(可参见<剑指offer>和leetcode:Intersection of Two Linked Lists)
1.0 先判断两条链表的长度;
1.1 从头节点开始走,更长的链表先走"长度之差"步,然后一起走,如果相遇,则为入口点(情况2);否则无交点(情况1)
2.都有环的情况,这种情况还要细分:
2.0 先判断两链表环入口点是否相同,若相同,则为情况4,转入步骤2.1;若不同,则为情况5或6,转入2.2;
2.1 如果为上图中情况4,我们可以把两链表交点作为"假想的尾部节点",然后就退化成两个无环链表找交点的问题了;
2.2 为判断两链表是否有交点,我们可以从第一个环的入口节点的下一个节点开始next,如果遇到了第二个链表环的入口节点,则返回第一个链表的入口节点(情况5:题目说找出第一个相交的节点,其实我觉得返回第二个链表的入口节点也行);反之,若走了一圈没遇到第二个链表环的入口节点,说明两链表不相交(情况6);
至此,程序执行结束.设计很巧妙,要熟练掌握.
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:最短路径算法
- C++ rand函数 2020-06-10
- OpenCV开发笔记(五十九):红胖子8分钟带你深入了解分水岭 2020-05-24
- 类欧几里得算法 2020-05-16
- 算法笔记刷题6 ( PAT 1003我要通过 ) 2020-05-08
- C语言实现经典游戏——扫雷! 2020-04-17
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash