Given two sorted arrays arr1 and arr2 of size m and n respectively, return the median of the two sorted arrays.
The median is defined as the middle value of a sorted list of numbers. In case the length of the list is even, the median is the average of the two middle elements.
Input: arr1 = [2, 4, 6], arr2 = [1, 3, 5]
Output: 3.5
Explanation: The array after merging arr1 and arr2 will be [ 1, 2, 3, 4, 5, 6 ]. As the length of the merged list is even, the median is the average of the two middle elements. Here two medians are 3 and 4. So the median will be the average of 3 and 4, which is 3.5.
Input: arr1 = [2, 4, 6], arr2 = [1, 3]
Output: 3.0
Explanation: The array after merging arr1 and arr2 will be [ 1, 2, 3, 4, 6 ]. The median is simply 3.
Input: arr1 = [2, 4, 5], arr2 = [1, 6]
The extremely naive approach is to merge the two sorted arrays and then find the median of the final merged array. Given that the arrays are already sorted, the merge approach of the merge sort algorithm can be used. This approach iterates through both arrays, picking the smallest elements first and then the larger ones, resulting in a final sorted array.
index
= (sizeOfMergedArray) / 2, median will be the sum of element at 'index' and the element at 'index-1' divided by 2.#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
//Function to find the median of two sorted arrays.
double median(vector<int>& arr1, vector<int>& arr2) {
// Size of two given arrays
int n1 = arr1.size(), n2 = arr2.size();
vector<int> merged;
// Apply the merge step
int i = 0, j = 0;
while (i < n1 && j < n2) {
if (arr1[i] < arr2[j]) merged.push_back(arr1[i++]);
else merged.push_back(arr2[j++]);
}
// Copy the remaining elements
while (i < n1) merged.push_back(arr1[i++]);
while (j < n2) merged.push_back(arr2[j++]);
// Find the median
int n = n1 + n2;
if (n % 2 == 1) {
return (double)merged[n / 2];
}
double median = ((double)merged[n / 2] + (double)merged[(n / 2) - 1]) / 2.0;
return median;
}
};
int main() {
vector<int> a = {1, 4, 7, 10, 12};
vector<int> b = {2, 3, 6, 15};
// Create an instance of the Solution class
Solution sol;
// Print the median of the two sorted arrays
cout << "The median of two sorted arrays is " << fixed << setprecision(1)
<< sol.median(a, b) << '\n';
return 0;
}
import java.util.*;
class Solution {
//Function to find the median of two sorted arrays.
public double median(int[] arr1, int[] arr2) {
// Size of two given arrays
int n1 = arr1.length, n2 = arr2.length;
int[] merged = new int[n1 + n2];
// Apply the merge step
int i = 0, j = 0, k = 0;
while (i < n1 && j < n2) {
if (arr1[i] < arr2[j]) merged[k++] = arr1[i++];
else merged[k++] = arr2[j++];
}
// Copy the remaining elements
while (i < n1) merged[k++] = arr1[i++];
while (j < n2) merged[k++] = arr2[j++];
// Find the median
int n = n1 + n2;
if (n % 2 == 1) {
return (double) merged[n / 2];
}
double median = ((double) merged[n / 2] + (double) merged[(n / 2) - 1]) / 2.0;
return median;
}
public static void main(String[] args) {
int[] a = {1, 4, 7, 10, 12};
int[] b = {2, 3, 6, 15};
// Create an instance of the Solution class
Solution sol = new Solution();
// Print the median of the two sorted arrays
System.out.println("The median of two sorted arrays is " + sol.median(a, b));
}
}
class Solution:
#Function to find the median of two sorted arrays.
def median(self, arr1, arr2):
# Size of two given arrays
n1, n2 = len(arr1), len(arr2)
merged = []
# Apply the merge step
i, j = 0, 0
while i < n1 and j < n2:
if arr1[i] < arr2[j]:
merged.append(arr1[i])
i += 1
else:
merged.append(arr2[j])
j += 1
# Copy the remaining elements
while i < n1:
merged.append(arr1[i])
i += 1
while j < n2:
merged.append(arr2[j])
j += 1
# Find the median
n = n1 + n2
if n % 2 == 1:
return float(merged[n // 2])
median = (float(merged[n // 2]) + float(merged[(n // 2) - 1])) / 2.0
return median
if __name__ == "__main__":
a = [1, 4, 7, 10, 12]
b = [2, 3, 6, 15]
# Create an instance of the Solution class
sol = Solution()
# Print the median of the two sorted arrays
print("The median of two sorted arrays is", sol.median(a, b))
class Solution {
//Function to find the median of two sorted arrays.
median(arr1, arr2) {
// Size of two given arrays
let n1 = arr1.length, n2 = arr2.length;
let merged = [];
// Apply the merge step
let i = 0, j = 0;
while (i < n1 && j < n2) {
if (arr1[i] < arr2[j]) merged.push(arr1[i++]);
else merged.push(arr2[j++]);
}
// Copy the remaining elements
while (i < n1) merged.push(arr1[i++]);
while (j < n2) merged.push(arr2[j++]);
// Find the median
let n = n1 + n2;
if (n % 2 === 1) {
return merged[Math.floor(n / 2)];
}
let median = (merged[n / 2] + merged[(n / 2) - 1]) / 2.0;
return median;
}
}
const a = [1, 4, 7, 10, 12];
const b = [2, 3, 6, 15];
//Create an instance of Solution class
const sol = new Solution();
// Print the answer
console.log("The answer is:", sol.median(a, b));
The idea here is to optimize the extra space used in the brute-force approach by eliminating the array used to store the final merged result. Upon closer observation, it can be noticed that only the two middle elements at indices [(sum of the sizes of both arrays) / 2] and [((sum of the sizes of both arrays) / 2) - 1] are needed, rather than the entire merged array, to effectively solve the problem. Stick to the same basic approach, but instead of storing elements in a separate array, use a counter called cnt
to represent the imaginary third array's index. While traversing through the arrays, when 'cnt' reaches either index (sum of size of both the arrays)/2 or ((sum of size of both the arrays)/2)-1, store that particular element. This way, the same goal can be achieved without using any extra space.
ind1
and ind2
. Else, median will be the element at indexind2
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
//Function to find the median of two sorted arrays.
double median(vector<int>& arr1, vector<int>& arr2) {
// Size of two given arrays
int n1 = arr1.size(), n2 = arr2.size();
int n = n1 + n2; // Total size
// Required indices for median calculation
int ind2 = n / 2;
int ind1 = ind2 - 1;
int cnt = 0;
int ind1el = -1, ind2el = -1;
// Apply the merge step
int i = 0, j = 0;
while (i < n1 && j < n2) {
if (arr1[i] < arr2[j]) {
if (cnt == ind1) ind1el = arr1[i];
if (cnt == ind2) ind2el = arr1[i];
cnt++;
i++;
} else {
if (cnt == ind1) ind1el = arr2[j];
if (cnt == ind2) ind2el = arr2[j];
cnt++;
j++;
}
}
// Copy the remaining elements
while (i < n1) {
if (cnt == ind1) ind1el = arr1[i];
if (cnt == ind2) ind2el = arr1[i];
cnt++;
i++;
}
while (j < n2) {
if (cnt == ind1) ind1el = arr2[j];
if (cnt == ind2) ind2el = arr2[j];
cnt++;
j++;
}
// Find the median
if (n % 2 == 1) {
return (double) ind2el;
}
return (double) ((double) (ind1el + ind2el)) / 2.0;
}
};
int main() {
vector<int> a = {1, 4, 7, 10, 12};
vector<int> b = {2, 3, 6, 15};
// Create an instance of the Solution class
Solution sol;
// Print the median of the two sorted arrays
cout << "The median of two sorted arrays is " << fixed << setprecision(1)
<< sol.median(a, b) << '\n';
return 0;
}
import java.util.Arrays;
class Solution {
//Function to find the median of two sorted arrays.
public double median(int[] arr1, int[] arr2) {
// Size of two given arrays
int n1 = arr1.length, n2 = arr2.length;
int n = n1 + n2; // Total size
// Required indices for median calculation
int ind2 = n / 2;
int ind1 = ind2 - 1;
int cnt = 0;
int ind1el = -1, ind2el = -1;
// Apply the merge step
int i = 0, j = 0;
while (i < n1 && j < n2) {
if (arr1[i] < arr2[j]) {
if (cnt == ind1) ind1el = arr1[i];
if (cnt == ind2) ind2el = arr1[i];
cnt++;
i++;
} else {
if (cnt == ind1) ind1el = arr2[j];
if (cnt == ind2) ind2el = arr2[j];
cnt++;
j++;
}
}
// Copy the remaining elements
while (i < n1) {
if (cnt == ind1) ind1el = arr1[i];
if (cnt == ind2) ind2el = arr1[i];
cnt++;
i++;
}
while (j < n2) {
if (cnt == ind1) ind1el = arr2[j];
if (cnt == ind2) ind2el = arr2[j];
cnt++;
j++;
}
// Find the median
if (n % 2 == 1) {
return (double) ind2el;
}
return (double) ((double) (ind1el + ind2el)) / 2.0;
}
public static void main(String[] args) {
int[] a = {1, 4, 7, 10, 12};
int[] b = {2, 3, 6, 15};
// Create an instance of the Solution class
Solution sol = new Solution();
// Print the median of the two sorted arrays
System.out.printf("The median of two sorted arrays is %.1f\n", sol.median(a, b));
}
}
class Solution:
#Function to find the median of two sorted arrays.
def median(self, arr1, arr2):
# Size of two given arrays
n1, n2 = len(arr1), len(arr2)
n = n1 + n2 # Total size
# Required indices for median calculation
ind2 = n // 2
ind1 = ind2 - 1
cnt = 0
ind1el, ind2el = -1, -1
# Apply the merge step
i, j = 0, 0
while i < n1 and j < n2:
if arr1[i] < arr2[j]:
if cnt == ind1:
ind1el = arr1[i]
if cnt == ind2:
ind2el = arr1[i]
cnt += 1
i += 1
else:
if cnt == ind1:
ind1el = arr2[j]
if cnt == ind2:
ind2el = arr2[j]
cnt += 1
j += 1
# Copy the remaining elements
while i < n1:
if cnt == ind1:
ind1el = arr1[i]
if cnt == ind2:
ind2el = arr1[i]
cnt += 1
i += 1
while j < n2:
if cnt == ind1:
ind1el = arr2[j]
if cnt == ind2:
ind2el = arr2[j]
cnt += 1
j += 1
# Find the median
if n % 2 == 1:
return float(ind2el)
return float((ind1el + ind2el) / 2)
if __name__ == "__main__":
a = [1, 4, 7, 10, 12]
b = [2, 3, 6, 15]
# Create an instance of the Solution class
sol = Solution()
# Print the median of the two sorted arrays
print(f"The median of two sorted arrays is {sol.median(a, b)}")
class Solution {
//Function to find the median of two sorted arrays.
median(arr1, arr2) {
// Size of two given arrays
const n1 = arr1.length, n2 = arr2.length;
const n = n1 + n2; // Total size
// Required indices for median calculation
const ind2 = Math.floor(n / 2);
const ind1 = ind2 - 1;
let cnt = 0;
let ind1el = -1, ind2el = -1;
// Apply the merge step
let i = 0, j = 0;
while (i < n1 && j < n2) {
if (arr1[i] < arr2[j]) {
if (cnt === ind1) ind1el = arr1[i];
if (cnt === ind2) ind2el = arr1[i];
cnt++;
i++;
} else {
if (cnt === ind1) ind1el = arr2[j];
if (cnt === ind2) ind2el = arr2[j];
cnt++;
j++;
}
}
// Copy the remaining elements
while (i < n1) {
if (cnt === ind1) ind1el = arr1[i];
if (cnt === ind2) ind2el = arr1[i];
cnt++;
i++;
}
while (j < n2) {
if (cnt === ind1) ind1el = arr2[j];
if (cnt === ind2) ind2el = arr2[j];
cnt++;
j++;
}
// Find the median
if (n % 2 === 1) {
return ind2el;
}
return (ind1el + ind2el) / 2;
}
}
const a = [1, 4, 7, 10, 12];
const b = [2, 3, 6, 15];
// Create an instance of the Solution class
const sol = new Solution();
// Print the median of the two sorted arrays
console.log(`The median of two sorted arrays is ${sol.median(a, b)}`);
Here, the idea is to use the Binary Search algorithm to optimize the approach. The primary objective of Binary Search is to efficiently determine the appropriate half to eliminate, thereby reducing the search space by half. It achieves this by identifying a specific condition that ensures the target is not present in that half. Now, let’s observe how to apply binary search in this problem. First, we'll solve the problem where the sum of the sizes of both arrays is even; we'll consider the odd case later.
Observation: Assume, n = sum of size of both the arrays. Characteristics of each half is that it contains (n/2) elements. Each half contains x elements from the first array and [(n/2)-x] elements from the second array. The value of x might be different for the two halves. The unique configuration of halves: Considering different values of x, one can get different left and right halves(x = the number of elements taken from the first array for a particular half). Some different configurations for the above example are shown below: Median creates a partition on the final merged array: Upon closer observation, we can easily show that the median divides the final merged array into two halves. For example, How to solve the problem using the above observations:#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
//Function to find the median of two sorted arrays.
double median(vector<int>& arr1, vector<int>& arr2) {
// Size of two given arrays
int n1 = arr1.size(), n2 = arr2.size();
/* Ensure arr1 is not larger than
arr2 to simplify implementation*/
if (n1 > n2) return median(arr2, arr1);
int n = n1 + n2;
// Length of left half
int left = (n1 + n2 + 1) / 2;
// Apply binary search
int low = 0, high = n1;
while (low <= high) {
// Calculate mid index for arr1
int mid1 = (low + high) >> 1;
// Calculate mid index for arr2
int mid2 = left - mid1;
// Calculate l1, l2, r1, and r2
int l1 = (mid1 > 0) ? arr1[mid1 - 1] : INT_MIN;
int r1 = (mid1 < n1) ? arr1[mid1] : INT_MAX;
int l2 = (mid2 > 0) ? arr2[mid2 - 1] : INT_MIN;
int r2 = (mid2 < n2) ? arr2[mid2] : INT_MAX;
if (l1 <= r2 && l2 <= r1) {
// If condition for finding median
if (n % 2 == 1) return max(l1, l2);
else return (max(l1, l2) + min(r1, r2)) / 2.0;
}
else if (l1 > r2) {
// Eliminate the right half of arr1
high = mid1 - 1;
} else {
// Eliminate the left half of arr1
low = mid1 + 1;
}
}
// Dummy statement
return 0;
}
};
int main() {
vector<int> arr1 = {1, 4, 7, 10, 12};
vector<int> arr2 = {2, 3, 6, 15};
// Create an instance of the Solution class
Solution sol;
// Print the median of the two sorted arrays
cout << "The median of two sorted arrays is " << fixed << setprecision(1)
<< sol.median(arr1, arr2) << '\n';
return 0;
}
import java.util.*;
class Solution {
//Function to find the median of two sorted arrays.
public double median(int[] arr1, int[] arr2) {
// Size of two given arrays
int n1 = arr1.length, n2 = arr2.length;
/* Ensure arr1 is not larger than
arr2 to simplify implementation*/
if (n1 > n2) return median(arr2, arr1);
int n = n1 + n2;
// Length of left half
int left = (n1 + n2 + 1) / 2;
// Apply binary search
int low = 0, high = n1;
while (low <= high) {
// Calculate mid index for arr1
int mid1 = (low + high) >>> 1;
// Calculate mid index for arr2
int mid2 = left - mid1;
// Calculate l1, l2, r1, and r2
int l1 = (mid1 > 0) ? arr1[mid1 - 1] : Integer.MIN_VALUE;
int r1 = (mid1 < n1) ? arr1[mid1] : Integer.MAX_VALUE;
int l2 = (mid2 > 0) ? arr2[mid2 - 1] : Integer.MIN_VALUE;
int r2 = (mid2 < n2) ? arr2[mid2] : Integer.MAX_VALUE;
if (l1 <= r2 && l2 <= r1) {
// If condition for finding median
if (n % 2 == 1) return Math.max(l1, l2);
else return (Math.max(l1, l2) + Math.min(r1, r2)) / 2.0;
}
else if (l1 > r2) {
// Eliminate the right half of arr1
high = mid1 - 1;
} else {
// Eliminate the left half of arr1
low = mid1 + 1;
}
}
// Dummy statement
return 0;
}
public static void main(String[] args) {
int[] arr1 = {1, 4, 7, 10, 12};
int[] arr2 = {2, 3, 6, 15};
// Create an instance of the Solution class
Solution sol = new Solution();
// Print the median of the two sorted arrays
System.out.printf("The median of two sorted arrays is %.1f\n", sol.median(arr1, arr2));
}
}
class Solution:
#Function to find the median of two sorted arrays.
def median(self, arr1, arr2):
# Size of two given arrays
n1, n2 = len(arr1), len(arr2)
""" Ensure arr1 is not larger than
arr2 to simplify implementation"""
if n1 > n2:
return self.median(arr2, arr1)
n = n1 + n2
# Length of left half
left = (n1 + n2 + 1) // 2
# Apply binary search
low, high = 0, n1
while low <= high:
# Calculate mid index for arr1
mid1 = (low + high) // 2
# Calculate mid index for arr2
mid2 = left - mid1
# Calculate l1, l2, r1, and r2
l1 = arr1[mid1 - 1] if mid1 > 0 else float('-inf')
r1 = arr1[mid1] if mid1 < n1 else float('inf')
l2 = arr2[mid2 - 1] if mid2 > 0 else float('-inf')
r2 = arr2[mid2] if mid2 < n2 else float('inf')
if l1 <= r2 and l2 <= r1:
# If condition for finding median is satisfied
if n % 2 == 1:
return max(l1, l2)
else:
return (max(l1, l2) + min(r1, r2)) / 2.0
elif l1 > r2:
# Eliminate the right half of arr1
high = mid1 - 1
else:
# Eliminate the left half of arr1
low = mid1 + 1
# Dummy statement
return 0
if __name__ == "__main__":
arr1 = [1, 4, 7, 10, 12]
arr2 = [2, 3, 6, 15]
# Create an instance of the Solution class
sol = Solution()
# Print the median of the two sorted arrays
print(f"The median of two sorted arrays is {sol.median(arr1, arr2)}")
class Solution {
//Function to find the median of two sorted arrays.
median(arr1, arr2) {
// Size of two given arrays
const n1 = arr1.length, n2 = arr2.length;
/* Ensure arr1 is not larger than
arr2 to simplify implementation*/
if (n1 > n2) return this.median(arr2, arr1);
const n = n1 + n2; // Total length
// Length of left half
const left = Math.floor((n1 + n2 + 1) / 2);
// Apply binary search
let low = 0, high = n1;
while (low <= high) {
// Calculate mid index for arr1
const mid1 = Math.floor((low + high) / 2);
// Calculate mid index for arr2
const mid2 = left - mid1;
// Calculate l1, l2, r1, and r2
const l1 = (mid1 > 0) ? arr1[mid1 - 1] : -Infinity;
const r1 = (mid1 < n1) ? arr1[mid1] : Infinity;
const l2 = (mid2 > 0) ? arr2[mid2 - 1] : -Infinity;
const r2 = (mid2 < n2) ? arr2[mid2] : Infinity;
if (l1 <= r2 && l2 <= r1) {
// If condition for finding median is satisfied
if (n % 2 === 1) return Math.max(l1, l2);
else return (Math.max(l1, l2) + Math.min(r1, r2)) / 2.0;
} else if (l1 > r2) {
// Eliminate the right half of arr1
high = mid1 - 1;
} else {
// Eliminate the left half of arr1
low = mid1 + 1;
}
}
// Dummy statement
return 0;
}
}
const arr1 = [1, 4, 7, 10, 12];
const arr2 = [2, 3, 6, 15];
// Create an instance of the Solution class
const sol = new Solution();
// Print the median of the two sorted arrays
console.log(`The median of two sorted arrays is ${sol.median(arr1, arr2)}`);
Q: What if the arrays have different sizes?
A: Binary search works regardless of the sizes of the arrays. The smaller array is chosen for the binary search to ensure efficiency, reducing the time complexity to O(log(min(m,n))).
Q: How does the algorithm ensure correctness for edge cases?
A: Special conditions handle scenarios like: partitionX=0: All elements in the left partition come from arr2. partitionX=m: All elements in the right partition come from arr2.
Q: Can this approach be extended to more than two arrays?
A: For k sorted arrays, use a priority queue (min-heap) to merge them while keeping track of their elements. After merging, compute the median in O(klogk+n).
Q: What if the arrays contain duplicates?
A: The algorithm handles duplicates naturally. The median is determined based on the partitioned halves, irrespective of repeated values.