ArrayProblem 35 of 36
Median of 2 sorted arrays of equal size
Problem Statement
Given two sorted arrays of equal size n, find the median of the merged array. The median is the middle element if the total number is odd, or the average of two middle elements if even.
Since both arrays have size n, the merged array has 2n elements (even), so median = (element at n-1 + element at n) / 2.
Example:
- Input:
arr1 = [1, 12, 15, 26, 38],arr2 = [2, 13, 17, 30, 45] - Output:
16 - Explanation: Merged array: [1, 2, 12, 13, 15, 17, 26, 30, 38, 45]. Median = (15 + 17) / 2 = 16.
Approach 1: Brute Force (Merge Arrays)
Intuition
Merge both arrays and find the median directly from the merged array.
Algorithm
- Merge both sorted arrays
- Find the two middle elements
- Return their average
java
public class Solution {
public double findMedian(int[] arr1, int[] arr2) {
int n = arr1.length;
int[] merged = new int[2 * n];
int i = 0, j = 0, k = 0;
// Merge both arrays
while (i < n && j < n) {
if (arr1[i] <= arr2[j]) {
merged[k++] = arr1[i++];
} else {
merged[k++] = arr2[j++];
}
}
while (i < n) merged[k++] = arr1[i++];
while (j < n) merged[k++] = arr2[j++];
// Find median
return (merged[n - 1] + merged[n]) / 2.0;
}
}Complexity Analysis
- Time Complexity: O(n) - Merge operation takes linear time
- Space Complexity: O(n) - Merged array storage
Approach 2: Count Without Merging
Intuition
We don't need to store all merged elements. Just count to the middle positions.
Algorithm
- Use two pointers to traverse both arrays
- Count elements until we reach positions n-1 and n
- Return average of these two elements
java
public class Solution {
public double findMedian(int[] arr1, int[] arr2) {
int n = arr1.length;
int i = 0, j = 0;
int count = 0;
int m1 = -1, m2 = -1; // Two middle elements
while (count <= n) {
// m1 becomes previous m2
m1 = m2;
// Get next smallest element
if (i == n) {
m2 = arr2[j++];
} else if (j == n) {
m2 = arr1[i++];
} else if (arr1[i] <= arr2[j]) {
m2 = arr1[i++];
} else {
m2 = arr2[j++];
}
count++;
}
return (m1 + m2) / 2.0;
}
}Complexity Analysis
- Time Complexity: O(n) - Traverse until middle
- Space Complexity: O(1) - Only constant extra space
Approach 3: Optimal - Binary Search
Intuition
Use binary search to find the correct partition point. The median divides the merged array such that left half has n elements.
Algorithm
- Binary search on smaller array for partition point
- Partition divides both arrays such that all left elements ≤ all right elements
- Median is average of max(left) and min(right)
java
public class Solution {
public double findMedian(int[] arr1, int[] arr2) {
int n = arr1.length;
// Ensure arr1 is smaller
if (arr1.length > arr2.length) {
return findMedian(arr2, arr1);
}
int low = 0, high = n;
while (low <= high) {
int cut1 = (low + high) / 2;
int cut2 = n - cut1;
// Elements on left and right of partition
int left1 = (cut1 == 0) ? Integer.MIN_VALUE : arr1[cut1 - 1];
int left2 = (cut2 == 0) ? Integer.MIN_VALUE : arr2[cut2 - 1];
int right1 = (cut1 == n) ? Integer.MAX_VALUE : arr1[cut1];
int right2 = (cut2 == n) ? Integer.MAX_VALUE : arr2[cut2];
// Valid partition found
if (left1 <= right2 && left2 <= right1) {
return (Math.max(left1, left2) + Math.min(right1, right2)) / 2.0;
}
if (left1 > right2) {
high = cut1 - 1;
} else {
low = cut1 + 1;
}
}
return 0.0; // Should never reach here
}
}Complexity Analysis
- Time Complexity: O(log n) - Binary search on one array
- Space Complexity: O(1) - Only constant extra space
Approach 4: Divide and Conquer
Intuition
Compare medians of both arrays. If they're equal, that's the answer. Otherwise, discard half of each array where median can't exist.
Algorithm
- Find medians m1 and m2 of both arrays
- If m1 == m2, return m1
- If m1 < m2, median is in [m1, end of arr1] and [start of arr2, m2]
- Recursively solve for reduced arrays
java
public class Solution {
public double findMedian(int[] arr1, int[] arr2) {
int n = arr1.length;
return findMedianUtil(arr1, 0, n - 1, arr2, 0, n - 1);
}
private int median(int[] arr, int start, int end) {
int n = end - start + 1;
if (n % 2 == 0) {
return (arr[start + n/2 - 1] + arr[start + n/2]) / 2;
}
return arr[start + n/2];
}
private int findMedianUtil(int[] arr1, int s1, int e1,
int[] arr2, int s2, int e2) {
int n = e1 - s1 + 1;
// Base cases
if (n == 1) {
return (arr1[s1] + arr2[s2]) / 2;
}
if (n == 2) {
return (Math.max(arr1[s1], arr2[s2]) + Math.min(arr1[e1], arr2[e2])) / 2;
}
int m1 = median(arr1, s1, e1);
int m2 = median(arr2, s2, e2);
if (m1 == m2) {
return m1;
}
int halfLen = (n - 1) / 2;
if (m1 < m2) {
return findMedianUtil(arr1, s1 + halfLen, e1, arr2, s2, e2 - halfLen);
} else {
return findMedianUtil(arr1, s1, e1 - halfLen, arr2, s2 + halfLen, e2);
}
}
}Complexity Analysis
- Time Complexity: O(log n) - Problem size halves each iteration
- Space Complexity: O(log n) - Recursion stack
Key Takeaways
- Equal size simplifies - We know exactly n elements on each side
- Binary search on partition - Find correct cut point in O(log n)
- Divide and conquer - Compare medians and discard half
- Edge cases - Handle INT_MIN/INT_MAX for boundary partitions
- Foundation for different sizes - Same technique extends to unequal arrays