# #3 160. Intersection of Two Linked Lists ###### tags:`linked list` `easy` `leetcode` ## Problem Given the heads of two singly linked-lists `headA` and `headB`, return the node at which the two lists intersect. If the two linked lists have no intersection at all, return `null`. For example, the following two linked lists begin to intersect at node `c1`: <br/> ![](https://i.imgur.com/nTgZ7zl.png) <br/> The test cases are generated such that there are no cycles anywhere in the entire linked structure. **Note** that the linked lists must **retain their original structure** after the function returns <br/> **Custom Judge:** The inputs to the **judge** are given as follows (your program is **not** given these inputs): - `intersectVal` - The value of the node where the intersection occurs. This is 0 if there is no intersected node. - `listA` - The first linked list. - `listB` - The second linked list. - `skipA` - The number of nodes to skip ahead in `listA` (starting from the head) to get to the intersected node. - `skipB` - The number of nodes to skip ahead in `listB` (starting from the head) to get to the intersected node. The judge will then create the linked structure based on these inputs and pass the two heads, `headA` and `headB` to your program. If you correctly return the intersected node, then your solution will be **accepted**. - testcase: ``` 8 [4,1,8,4,5] [5,6,1,8,4,5] 2 3 ``` ### Sample Input & Output #### Example 1 ![](https://i.imgur.com/EPCXvus.png) ```javascript Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3 Output: Intersected at '8' Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B. ``` #### Example 2 ![](https://i.imgur.com/ZJJmxMx.png) ```javascript Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 Output: Intersected at '2' Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [1,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B. ``` #### Example 3 ![](https://i.imgur.com/eGI2Foo.png) ```javascript Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 Output: No intersection Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values. Explanation: The two lists do not intersect, so return null. ``` ### Constraints - `intersectVal == listA[skipA] == listB[skipB]` if `listA` and `listB` intersect. ### Follow up Could you write a solution that runs in `O(m + n)` time and use only `O(1)` memory? <br> ## Solutions ### Official none. <br> --- ### Everyone's #### solution 1: record the nodes :::spoiler 月 ```javascript= var getIntersectionNode = function(headA, headB) { // Time O(a+b) Space O(a) // a is the length of headA; b is the length of headB const recordSet = new Set(); // set headA node in recordSet while(headA) { recordSet.add(headA); headA = headA.next; } while(headB) { if (recordSet.has(headB)) { return headB; } headB = headB.next; } return null; }; ``` ::: <br> #### solution 2: truncate the list :::spoiler 東 ```javascript= // Time O(m+n), Space O(m+n) m, n is the amount of node of input headA, headB var getIntersectionNode = function(headA, headB) { let listA = headA; let listB = headB; const lenA = calculateLength(headA); const lenB = calculateLength(headB); if(lenA > lenB){ const AStartIdx = lenA - lenB; listA = moveListToIdx(listA, AStartIdx); } else{ const BStartIdx = lenB - lenA; listB = moveListToIdx(listB, BStartIdx); } while(listA !== null){ if(listA === listB){ return listA; } listA = listA.next; listB = listB.next; } return null; }; function calculateLength(list){ let count = 0; while(list !== null){ count ++; list = list.next; } return count; } function moveListToIdx(list, idx){ while(idx > 0){ list = list.next; idx --; } return list; } ``` ::: <br/> #### solution 3: loop the list :::spoiler Raiy ```javascript= var getIntersectionNode = function(headA, headB) { // time: O(n+m)? space: O(1) n = headA length, m = headB length // -> time: O(n*m) : the worst case if(!headA || !headB) return null let currentA = headA let currentB = headB while(currentA !== currentB){ currentA = currentA.next currentB = currentB.next if(currentA === currentB){ return currentA } if(!currentA) currentA = headA if(!currentB) currentB = headB } return currentA }; ``` ::: <br> #### solution 4: concatenate two lists :::spoiler YC ```javascript= /* * time: O(m+n), where m is the number of nodes in the headA, n is the number of nodes in the headB * space: O(1) */ var getIntersectionNode = function(headA, headB) { let listA = headA; let listB = headB; while(listA !== listB){ listA = listA === null ? headB : listA.next; listB = listB === null ? headA : listB.next; } return listA; }; ``` ::: :::spoiler Becky ```javascript= //time: O(n) | space: O(1) //-> time: O(m+n) var getIntersectionNode = function(headA, headB) { let a = headA; let b = headB; while (a != b) { if(a === null){ a = headB; }else{ a = a.next; } if(b === null){ b = headA; }else{ b = b.next } } return a; }; ``` ::: <br> <br> #### backlog :::spoiler Hao ```javascript= ``` ::: <br> :::spoiler SOL ```javascript= ``` ::: --- ## Supplement / Discussion ![](https://i.imgur.com/3bY6kiv.png) (示意圖) ### Thinking 1 直觀的做法:把 A 的 node 存起來,遍歷 B 找重複的點 ### Thinking 2 直觀的做法:既然 B 比 A 長,那就讓 B 從 b2 開始判斷。 > 計算 A, B 的總長,取差值 `B - A`,loop 找出 c1 ``` A: a1 c1 c2 B: b1 b2 c1 c2 ⬇️ A: a1 c1 c2 B: b2 c1 c2 ``` ### Thinking 3 如果 A 和 B 同時從頭開始尋找相交的點,會在什麼時候找到 c1 > list 不斷重複自己 ``` A: a1 c1 c2| a1 c1 c2| a1 c1 c2| a1 c1 c2 B: b1 b2 c1 c2| b1 b2 c1 c2| b1 b2 c1 c2 ``` 在 A 重複自己四次、B 重複自己三次後,找到 c1 了 :::info 有發現什麼有趣的現象嗎? ::: ### Thinking 4 :::info 從 Thinking 3 可以發現,出現相交的點後,A 和 B 最後的長度會一樣長。 ::: 還有其他方法可以讓兩者的長度一樣嗎? > A + B = B + A :::spoiler 回頭看看 Follow up Could you write a solution that runs in `O(m + n)` time and use only `O(1)` memory? ::: <br/> ``` A: a1 c1 c2 B: b1 b2 c1 c2 ⬇️ A + B: a1 c1 c2| b1 b2 c1 c2 B + A: b1 b2 c1 c2| a1 c1 c2 ```