I was stuck on this problem for like 2 days until I finally decided to see the solution..... (rip). This is my solution + some notes to this problem.. thank u
Problem statement (Leetcode Hard)
Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
Solution
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int[] A = nums1;
int[] B = nums2;
int total = A.length + B.length;
// int half = total / 2;
int half = (total + 1) / 2; // we + 1 to make sure the median is always on the left partition
// make A the shorter one
if (B.length < A.length) {
int[] tmp = A;
A = B;
B = tmp;
}
int l = 0;
int r = A.length;
// it's not A.length - 1 because i or j represents the start of the right (the "cut")
// we need this to consider the case where ALL elements are in the left side (and 0 to the right)
while (l <= r) {
int i = (l + r) / 2; // start of ARight.. or more like a place to "cut"
int j = half - i; // start of BRight
int Aleft = i > 0 ? A[i - 1] : Integer.MIN_VALUE;
int Aright = i < A.length ? A[i] : Integer.MAX_VALUE;
int Bleft = j > 0 ? B[j - 1] : Integer.MIN_VALUE;
int Bright = j < B.length ? B[j] : Integer.MAX_VALUE;
if (Aleft <= Bright && Bleft <= Aright) {
if (total % 2 != 0) { // total is odd, return the max of the lefts
return Math.max(Aleft, Bleft);
} else { // total is even, we get the middle (max of lefts + min of rights) / 2
return (Math.max(Aleft, Bleft) + Math.min(Aright, Bright)) / 2.0;
}
} else if (Aleft > Bright) {
r = i - 1;
} else {
l = i + 1;
}
}
return -1;
}
}
Concept
- Imagine we merged those 2 arrays. We want to get the Left partition and the Right partition, then get the median.
- But since we canāt merge, we need to find the partition (cut) that divides the combined set of numbers into 2 equal halves (left and right)
Strategy
(shoutout to neetcode)
- The main idea is that we have a Left and Right partition, and we check
Aleft <= Bright && Bleft <= Aright - If so, that means we have successfully found the left and right partition
- If total is an odd number, then get
Main.min(Aright, Bright) - If total is an even number, get
(Math.max(Aleft, Bleft) + Math.min(Aright, Bright)) / 2
- If total is an odd number, then get
- If not, if
Aleft > Bright- That means when we combine all our lefts, in the left partition we have an element that is bigger than one element on the right partition
- we have to shrink
Aleftand expandingBleft, sor = i - 1
- else (
Bleft > Aright)- That means when we combine all our lefts, in the left partition we have an element that is bigger than one element on the right partition
- we have to shrink
Bleftand expandingAleft->l = i + 1
Things to note
int total = A.length + B.length;, andint half = (total + 1) / 2- we
+ 1to make sure the median is always on the left partition - If total is
10, then10 + 15/ 2 = 6(L and R has same # of elems). If total is11, then11 + 1 / 2 = 6(L has 6, R has 5).- Both cases, L is either same or larger than R, so median will always be in L
- we
int l = 0andint r = A.length- We do
r = A.lengthand notA.length - 1because we want to allow the possibility that ALL elements of A are smaller than the median (they are all Left partition and NO right partition) - If
Bleft > Aright: l = i + 1(the else case)- (Tracing example with
A = [1,2], B = [3,4,5,6]) lcan reach up tor, theni = (1+r)/2can be exactlyA.length, which means all ofAis in the left partition
- (Tracing example with
- We do
- The
Integer.MIN_VALUEandInteger.MAX_VALUE- We give the
MIN_VALUEto the lefts and theMAX_VALUEto the rights because if they are out of bounds, when we compare the check we want it to pass
- We give the
Time Complexity
-
We actively look for the "cut" position
i(the start ofAright, which ranges from 0 toA.length) using binary search. -
The problem states that the solution must run Ā time.
- This would be the case if we had done a brute force solution - merging arrays together and then finding the median.
-
But in the problem, we're actually just doing binary search on the shorter array (which is
Ain our case), so the actual time complexity is .