Intersection of Two Linked Lists
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3
begin to intersect at node c1.
Notes:
- If the two linked lists have no intersection at all, return
null
. - The linked lists must retain their original structure after the function returns.
- You may assume there are no cycles anywhere in the entire linked structure.
- Your code should preferably run in O(n) time and use only O(1) memory.
Credits:
Special thanks to @stellari for adding this problem and creating all test cases.
SOLUTION 1:
1.各自遍历链表,分别取得长度;
2.较长一条链表移动abs(lengthA-lengthB)个节点;
3.同时移动指针,判断是否相等。
(O(n+m) running time, O(1) memory)
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { 12 13 //my solution 14 if(headA == NULL && headB == NULL) { 15 return NULL; 16 } 17 if(headA && headB) { 18 ListNode *it; 19 it = headA; 20 int lengthA = 0; 21 while(it) { 22 lengthA++; 23 it = it->next; 24 } 25 it = headB; 26 int lengthB = 0; 27 while(it) { 28 lengthB++; 29 it = it->next; 30 } 31 it = NULL; 32 ListNode *itA = headA; 33 ListNode *itB = headB; 34 35 if(lengthA > lengthB) { 36 for(int i = 0; i < lengthA-lengthB; i++) { 37 itA = itA->next; 38 } 39 } else { 40 for(int i = 0; i < lengthB-lengthA; i++) { 41 itB = itB->next; 42 } 43 } 44 while(itA != itB) { 45 itA = itA->next; 46 itB = itB->next; 47 } 48 return itA; 49 } else { 50 return NULL; 51 } 52 }
SOLUTION 2:
LeetCode提供的解法:
- Hashset solution (O(n+m) running time, O(n) or O(m) memory):
Traverse list A and store the address / reference to each node in a hash set. Then check every node bi in list B: if bi appears in the hash set, then bi is the intersection node.
这样做比较占用空间。没有去写这个解法的代码;
SOLUTION 3:
LeetCode的解法:
Two pointer solution (O(n+m) running time, O(1) memory):
- Maintain two pointers pA and pB initialized at the head of A and B, respectively. Then let them both traverse through the lists, one node at a time.
- When pA reaches the end of a list, then redirect it to the head of B (yes, B, that's right.); similarly when pB reaches the end of a list, redirect it the head of A.
- If at any point pA meets pB, then pA/pB is the intersection node.
- To see why the above trick would work, consider the following two lists: A = {1,3,5,7,9,11} and B = {2,4,9,11}, which are intersected at node '9'. Since B.length (=4) < A.length (=6), pB would reach the end of the merged list first, because pB traverses exactly 2 nodes less than pA does. By redirecting pB to head A, and pA to head B, we now ask pB to travel exactly 2 more nodes than pA would. So in the second iteration, they are guaranteed to reach the intersection node at the same time.
- If two lists have intersection, then their last nodes must be the same one. So when pA/pB reaches the end of a list, record the last element of A/B respectively. If the two last elements are not the same one, then the two lists have no intersections.
其实本质和solution 1 差不多,都是把两个链表的长度差消去。但是这样写感觉很屌。
自己写的代码:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { 12 13 // solution 3 14 if(headA == NULL && headB == NULL) { 15 return NULL; 16 } 17 if(headA && headB){ 18 ListNode *pA = headA; 19 ListNode *pB = headB; 20 while(pA != pB){ 21 if(pA == NULL && pB == NULL){ 22 return NULL; 23 } 24 if(pA == NULL){ 25 pA = headB; 26 } 27 if(pB == NULL){ 28 pB = headA; 29 } 30 //if the intersection is the last node 31 if(pA == pB){ 32 return pA; 33 } 34 pA = pA->next; 35 pB = pB->next; 36 } 37 return pA; 38 } 39 return NULL; 40 } 41 };