Skip to content

Commit 3e7ff67

Browse files
chore: Merge pull request #149 from saulmaldonado/feat/intersection-of-two-linked-lists
intersection of two linked lists
2 parents 12c6548 + 3cf1cf6 commit 3e7ff67

12 files changed

+232
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Intersection of Two Linked Lists
2+
3+
## Difficulty
4+
5+
![Easy](https://img.shields.io/badge/easy-5cb85c?style=for-the-badge&logoColor=white)
6+
7+
## Problem
8+
9+
Write a program to find the node at which the intersection of two singly linked lists begins.
10+
11+
For example, the following two linked lists:
12+
13+
![Example](./images/example-1.png)
14+
15+
### Example 1
16+
17+
![Example 1](./images/example-2.png)
18+
19+
```
20+
Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
21+
Output: Reference of the node with value = 8
22+
Input 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.
23+
```
24+
25+
### Example 2
26+
27+
![Example 2](./images/example-3.png)
28+
29+
```
30+
Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
31+
Output: Reference of the node with value = 2
32+
Input 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.
33+
```
34+
35+
### Example 3
36+
37+
![Example 3](./images/example-4.png)
38+
39+
```
40+
Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
41+
Output: null
42+
Input 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.
43+
Explanation: The two lists do not intersect, so return null.
44+
```
45+
46+
### Constraints
47+
48+
`If the two linked lists have no intersection at all, return null.`
49+
50+
`The linked lists must retain their original structure after the function returns.`
51+
52+
`You may assume there are no cycles anywhere in the entire linked structure.`
53+
54+
`Each value on each linked list is in the range [1, 10^9].`
55+
56+
`Your code should preferably run in O(n) time and use only O(1) memory.`
57+
58+
<details>
59+
<summary>Solutions (Click to expand)</summary>
60+
61+
### Explanation
62+
63+
#### Difference In Length
64+
65+
We can separate the combined LinkedList into 3 parts
66+
67+
1. The shared sublist. These are the nodes that both the A list and the B list have in common
68+
2. The A sublist. These are the nodes that are unique to A
69+
3. The B sublist. These are the nodes that are unique to B
70+
71+
If we want the two lists to intersect there must be least one shared node. We will use two pointers to traverse the lists. Our goal is to get both pointers on the same shared node.
72+
73+
![Two Pointers](./images/solution-1.png)
74+
75+
Ideally, if we were to increment both pointers at the same time we would intersect at the first shared node. However if the sublists leading up to the first shared node are not the same length then the pointers will never intersect.
76+
This is because the `A` pointer has to travel `subListA.length` nodes to get to the first shared node and the `B` pointer has to travel `subListB.length` node to get to the first shared node.
77+
if `subListA.length < subListB.length` then the `A` pointer will always be `subListB.length - subListA.length` ahead of the `B` pointer when both are in the shared sublist.
78+
79+
If we want both pointers to intersect at the first shared node then we have to make `subListA.length == subListB.length`. This would mean starting the `B` pointer `subListB.length - subListA.length` ahead of `headB`. This would effectively cause both pointers to travel the same number of nodes before intersecting at the first shared node.
80+
81+
Before we can do this we need to know that length of the `A` list and the `B` list. If we have `aList.length` and `bList.length` then we can find the number of node that the `A` pointer needs to travel to get its head start.
82+
83+
We also do the same without calculating the difference in length. If we move the `A` pointer `bList.length` nodes where we overflow `bList.length - aList.length` into the `B` list and we move the `B` pointer `bList.length` nodes where we overflow into the beginning of the `A` list, we would eventually reach a point where the both pointers are `n` nodes from the first shared node
84+
85+
![Two Pointers Overflow](./images/solution-2.png)
86+
87+
From there on we would advance both pointers until they both intersect.
88+
89+
![Intersect](./images/solution-3.png)
90+
91+
Time: `O(N + M)` Where `N` and `M` are the lengths of both lists
92+
93+
Space: `O(1)`
94+
95+
- [JavaScript](./intersection-of-two-linked-lists.js)
96+
- [TypeScript](./intersection-of-two-linked-lists.ts)
97+
- [Java](./intersection-of-two-linked-lists.java)
98+
- [Go](./intersection-of-two-linked-lists.go)
99+
100+
</details>
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package intersectionoftwolinkedlists
2+
3+
type ListNode struct {
4+
Val int
5+
Next *ListNode
6+
}
7+
8+
func getIntersectionNode(headA, headB *ListNode) *ListNode {
9+
if headA == nil || headB == nil {
10+
return nil
11+
}
12+
13+
aPointer := headA
14+
bPointer := headB
15+
16+
for aPointer != bPointer {
17+
aPointer = aPointer.Next
18+
bPointer = bPointer.Next
19+
20+
if aPointer == bPointer {
21+
return aPointer
22+
}
23+
24+
if aPointer == nil {
25+
aPointer = headB
26+
}
27+
28+
if bPointer == nil {
29+
bPointer = headA
30+
}
31+
}
32+
33+
return aPointer
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Definition for singly-linked list. public class ListNode { int val; ListNode
3+
* next; ListNode(int x) { val = x; next = null; } }
4+
*/
5+
public class Solution {
6+
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
7+
8+
if (headA == null || headB == null) {
9+
return null;
10+
}
11+
12+
ListNode aPointer = headA;
13+
ListNode bPointer = headB;
14+
15+
while (aPointer != bPointer) {
16+
aPointer = aPointer.next;
17+
bPointer = bPointer.next;
18+
19+
if (aPointer == bPointer) {
20+
return aPointer;
21+
}
22+
23+
if (aPointer == null) {
24+
aPointer = headB;
25+
}
26+
27+
if (bPointer == null) {
28+
bPointer = headA;
29+
}
30+
}
31+
32+
return aPointer;
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
function ListNode(val) {
2+
this.val = val;
3+
this.next = null;
4+
}
5+
6+
/**
7+
* @param {ListNode} headA
8+
* @param {ListNode} headB
9+
* @return {ListNode}
10+
*/
11+
function getIntersectionNode(headA, headB) {
12+
if (headA === null || headB === null) {
13+
return null;
14+
}
15+
16+
let aPointer = headA;
17+
let bPointer = headB;
18+
19+
while (aPointer != bPointer) {
20+
aPointer = aPointer.next;
21+
bPointer = bPointer.next;
22+
23+
if (aPointer == bPointer) {
24+
return aPointer;
25+
}
26+
27+
if (aPointer == null) {
28+
aPointer = headB;
29+
}
30+
31+
if (bPointer == null) {
32+
bPointer = headA;
33+
}
34+
}
35+
36+
return aPointer;
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
2+
if (headA === null || headB === null) {
3+
return null;
4+
}
5+
6+
let aPointer: ListNode | null = headA;
7+
let bPointer: ListNode | null = headB;
8+
9+
while (aPointer != bPointer) {
10+
aPointer = aPointer.next;
11+
bPointer = bPointer.next;
12+
13+
if (aPointer == bPointer) {
14+
return aPointer;
15+
}
16+
17+
if (aPointer == null) {
18+
aPointer = headB;
19+
}
20+
21+
if (bPointer == null) {
22+
bPointer = headA;
23+
}
24+
}
25+
26+
return aPointer;
27+
}

0 commit comments

Comments
 (0)