On this page

Union of Two Sorted Arrays

Given two sorted arrays a[] and b[], where each array may contain duplicate elements, return the union of the two arrays in sorted order.

The union is the set of distinct elements that are present in either of the arrays.

Constraints:

  • 1 <= a.size(), b.size() <= 10^5
  • -10^9 <= a[i], b[i] <= 10^9
Example 1:
Input: a[] = [1, 2, 3, 4, 5], b[] = [1, 2, 3, 6, 7]
Output: [1, 2, 3, 4, 5, 6, 7]
Explanation: Distinct elements including both the arrays are: 1 2 3 4 5 6 7.
Example 2:
Input: a[] = [2, 2, 3, 4, 5], b[] = [1, 1, 2, 3, 4]
Output: [1, 2, 3, 4, 5]
Explanation: Distinct elements including both the arrays are: 1 2 3 4 5.
Example 3:
Input: a[] = [1, 1, 1, 1, 1], b[] = [2, 2, 2, 2, 2]
Output: [1, 2]
Explanation: Distinct elements including both the arrays are: 1 2.

Brute Force

Put every value from both arrays into an ordered set. A set keeps only one copy of each value, and an ordered set keeps them sorted.

  1. Create an empty ordered set.
  2. Insert every value of a into the set.
  3. Insert every value of b into the set.
  4. Copy the values from the set into the result, from smallest to largest.

This works, but it ignores that both arrays are already sorted. The set has to sort the values again, and it needs extra memory to hold them.

class Solution {
public:
vector<int> findUnion(vector<int>& a, vector<int>& b) {
set<int> uniqueValues;
for (int value : a) {
uniqueValues.insert(value);
}
for (int value : b) {
uniqueValues.insert(value);
}
vector<int> result;
for (int value : uniqueValues) {
result.push_back(value);
}
return result;
}
};
  • Time: O((n + m) log(n + m)). Ordering the values costs O(log) per insert.
  • Space: O(n + m). The set can hold every value.

Optimal Approach: Two Pointers

Both arrays are already sorted. So the smallest remaining value is always at the front of one of the two arrays. This is the same idea as merging two sorted lists, with one extra rule: skip duplicates.

We use:

  • i: pointer on array a.
  • j: pointer on array b.
  • result: the union we are building.

The duplicate rule: before adding a value, check the last value in result. If it is the same, skip it. Because everything arrives in sorted order, any duplicate is always right next to its copy.

Steps:

  1. Start i = 0 and j = 0.
  2. While both arrays have elements, pick the smaller of a[i] and b[j] and move that pointer forward.
  3. Add the picked value to result only if result is empty or its last value is different.
  4. When one array is finished, go through the rest of the other array with the same duplicate rule.
  5. Return result.
class Solution {
public:
vector<int> findUnion(vector<int>& a, vector<int>& b) {
int n = a.size();
int m = b.size();
int i = 0;
int j = 0;
vector<int> result;
while (i < n && j < m) {
int value;
if (a[i] <= b[j]) {
value = a[i];
i++;
} else {
value = b[j];
j++;
}
if (result.empty() || result.back() != value) {
result.push_back(value);
}
}
while (i < n) {
if (result.empty() || result.back() != a[i]) {
result.push_back(a[i]);
}
i++;
}
while (j < m) {
if (result.empty() || result.back() != b[j]) {
result.push_back(b[j]);
}
j++;
}
return result;
}
};

Complexity

Time: O(n + m)

Each step moves one pointer forward, so every element of both arrays is looked at exactly once.

Space: O(1) extra

Besides the output array, we only use the pointers i and j and one variable value. The output itself holds up to n + m values.

How to Explain It in an Interview

How to Explain it in an Interview

The 30-Second Spoken Pitch
"The simple idea is to put all the values from both arrays into an ordered set, which removes duplicates and keeps the values sorted, and then copy the set into the result. That is O of n plus m times log of n plus m time and O of n plus m space, and it ignores that both arrays are already sorted. A better way is two pointers. I keep one pointer on each array, and at each step I take the smaller of the two front values and move that pointer. Since the values come out in sorted order, any duplicate is right next to its copy, so before adding a value I only check the last value in the result. If it is the same, I skip it, otherwise I add it. When one array is finished, I go through the rest of the other array with the same check. The time complexity is O of n plus m and the extra space complexity is O of 1, not counting the output array."
Next TopicIntersection of Two Sorted Arrays