Task
Task:
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
This problem was taken from Leetcode
Solution
Using a brute force we could merge the two arrays and find the median, but this is slow.
To optimize the solution we could use one of the properties of the arrays: the arrays are sorted.
– We could substitute the problem of find the median with find the numbers that are not in the median
The solution:
Java Script
/** * @param {number[]} nums1 * @param {number[]} nums2 * @return {number} */ var findMedianSortedArrays = function(nums1, nums2) { function findMedianIndex(arr) { var median = 0; var i = 0; if(arr.length % 2) { var i = (arr.length / 2 + 0.5) - 1; median = arr[i]; } else { var i = (arr.length / 2); median = ((arr[i - 1] + arr[i]) / 2); } return median; } function isFirstArrayInTheMiddleOfSecondEvenArray(x, y) { var minX = x[0]; var maxX = x [1]; var medianY = Math.floor(y.length / 2); var leftMiddleY = y[medianY - 1]; var rightMiddleY = y[medianY]; return minX > leftMiddleY && maxX < rightMiddleY; } function findMedianOfArrayAndValue(arr, val) { if(arr.length == 0) { return val; } else if (typeof(val) == 'undefined') { return findMedianIndex(arr); } var median = 0; if(arr.length % 2) { // odd aray // var medianIndex = Math.floor((arr.length / 2)); // median = arr[medianIndex]; var arrMedian = findMedianIndex(arr); if(arrMedian > val) { // the median of merged array should lie on the left of arr <== var i = Math.floor(arr.length / 2); var right = arr[i]; var left = Math.max( arr[i - 1], val ); return findMedianIndex( [left, right] ); } else { // the median of merged array should lie on the right of arr ==> var i = Math.floor(arr.length / 2); var left = arr[i]; var right = Math.min( arr[i + 1], val ); return findMedianIndex( [left, right] ); } } else { // even aray var arrMedian = findMedianIndex(arr); if(arrMedian > val) { // the median of merged array should lie on the left of arr median <== var i = Math.floor((arr.length / 2) - 1); var left = arr[i]; return Math.max(left, val); } else { // the median lies on the right side ==> var i = (arr.length / 2); var right = arr[i]; return Math.min(right, val); } median = findMedianIndex( [ arr[medianIndex], arr[medianIndex + 1] ]); } return ( Math.min(median, val) + Math.max(median, val) ) / 2; } function findMedian(X, Y) { // check all odd cases if (X.length === 1 && Y.length === 1) { return (X[0] + Y[0]) / 2; } if(X.length <= 1) { return findMedianOfArrayAndValue(Y, X[0]); } else if(Y.length <= 1) { return findMedianOfArrayAndValue(X, Y[0]); } else if(X.length == 1 && Y.length == 1) { var testArray = [ X[0], Y[0] ]; return findMedianIndex(testArray); } else if(X.length < 1) { var testArray = Y.concat(X); return findMedianIndex(testArray); } else if( Y.length < 1) { var testArray = X.concat(Y); return findMedianIndex(testArray); } if( X.length === 2 && Y.length >= 2 && Y.length % 2 === 0) { if(isFirstArrayInTheMiddleOfSecondEvenArray(X, Y)) { /* in example: var X = [1, 2]; var Y = [-1, 3]; */ return (X[0] + X[1]) / 2; } } if( Y.length === 2 && X.length >= 2 && X.length % 2 === 0) { if(isFirstArrayInTheMiddleOfSecondEvenArray(Y, X)) { /* and the other way */ return (Y[0] + Y[1]) / 2; } } var mX = findMedianIndex(X); var mY = findMedianIndex(Y); if(mX == mY) { return mX; } var splicePart = Math.floor(Math.min(X.length / 2 - 1, Y.length / 2 - 1)); splicePart = splicePart < 1 ? 1 : splicePart; if (mX < mY) { X.splice(0, splicePart); Y.splice(Y.length - splicePart); } else { X.splice(X.length - splicePart); Y.splice(0, splicePart); } return findMedian(X, Y); } return findMedian(nums1, nums2); }