class Solution:
def arraysIntersection(self, arr1, arr2, arr3):
i, j, k = 0, 0, 0
res = []
while i < len(arr1) and j < len(arr2) and k < len(arr3):
if arr1[i] == arr2[j] == arr3[k]:
res.append(arr1[i])
i += 1
j += 1
k += 1
else:
min_val = min(arr1[i], arr2[j], arr3[k])
if arr1[i] == min_val:
i += 1
if arr2[j] == min_val:
j += 1
if arr3[k] == min_val:
k += 1
return res
class Solution {
public:
vector<int> arraysIntersection(vector<int>& arr1, vector<int>& arr2, vector<int>& arr3) {
int i = 0, j = 0, k = 0;
vector<int> res;
while (i < arr1.size() && j < arr2.size() && k < arr3.size()) {
if (arr1[i] == arr2[j] && arr2[j] == arr3[k]) {
res.push_back(arr1[i]);
i++; j++; k++;
} else {
int min_val = min(arr1[i], min(arr2[j], arr3[k]));
if (arr1[i] == min_val) i++;
if (arr2[j] == min_val) j++;
if (arr3[k] == min_val) k++;
}
}
return res;
}
};
class Solution {
public List<Integer> arraysIntersection(int[] arr1, int[] arr2, int[] arr3) {
int i = 0, j = 0, k = 0;
List<Integer> res = new ArrayList<>();
while (i < arr1.length && j < arr2.length && k < arr3.length) {
if (arr1[i] == arr2[j] && arr2[j] == arr3[k]) {
res.add(arr1[i]);
i++; j++; k++;
} else {
int minVal = Math.min(arr1[i], Math.min(arr2[j], arr3[k]));
if (arr1[i] == minVal) i++;
if (arr2[j] == minVal) j++;
if (arr3[k] == minVal) k++;
}
}
return res;
}
}
var arraysIntersection = function(arr1, arr2, arr3) {
let i = 0, j = 0, k = 0;
const res = [];
while (i < arr1.length && j < arr2.length && k < arr3.length) {
if (arr1[i] === arr2[j] && arr2[j] === arr3[k]) {
res.push(arr1[i]);
i++; j++; k++;
} else {
let minVal = Math.min(arr1[i], arr2[j], arr3[k]);
if (arr1[i] === minVal) i++;
if (arr2[j] === minVal) j++;
if (arr3[k] === minVal) k++;
}
}
return res;
};
Given three strictly increasing integer arrays arr1
, arr2
, and arr3
, your task is to return a sorted array containing only the integers that appear in all three arrays.
The first idea that comes to mind is to check every element of one array against the other two. For example, for each element in arr1
, we could check if it exists in arr2
and arr3
. However, this brute-force approach would be inefficient, especially for large arrays, since searching through arrays repeatedly can take a lot of time.
But since all arrays are sorted and strictly increasing, we can take advantage of this property. We can use a method similar to merging in merge sort, using three pointers to walk through the arrays in sync. This way, we only need to scan through each array once, comparing the current elements and advancing the pointers smartly.
i
for arr1
, j
for arr2
, k
for arr3
), all starting at 0.This approach ensures that we only look at each element once, making the solution efficient and elegant.
Let's walk through an example:
Input:
arr1 = [1, 2, 3, 4, 5]
arr2 = [1, 2, 5, 7, 9]
arr3 = [1, 3, 4, 5, 8]
i = 0, j = 0, k = 0
: All three arrays have 1
at these positions. Add 1
to result, increment all pointers.arr1[1]=2, arr2[1]=2, arr3[1]=3
: 2, 2, 3. The smallest is 2. Increment i
and j
(since both have 2).arr1[2]=3, arr2[2]=5, arr3[1]=3
: 3, 5, 3. The smallest is 3. Increment i
and k
(both have 3).arr1[3]=4, arr2[2]=5, arr3[2]=4
: 4, 5, 4. The smallest is 4. Increment i
and k
(both have 4).arr1[4]=5, arr2[2]=5, arr3[3]=5
: 5, 5, 5. All equal! Add 5
to result, increment all pointers.
Output: [1, 5]
arr1
, check if it exists in arr2
and arr3
. This would take O(N1 * (N2 + N3)) time, where N1, N2, N3 are the lengths of the arrays.
By leveraging the fact that the input arrays are strictly increasing and sorted, we can use three pointers to efficiently find the intersection. This method avoids unnecessary repeated scanning and ensures an optimal O(N1 + N2 + N3) time complexity. The approach is simple, intuitive, and highlights the power of utilizing input constraints to design efficient algorithms.