Median of Two Sorted Arrays
来源:互联网 发布:淘宝商家服务社区 编辑:程序博客网 时间:2024/06/16 02:28
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)).
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
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {int len1 = nums1.length;int len2 = nums2.length;int sum = len1 + len2;int median = sum >> 1;int[] numsTemp = null;int[] numsTempOr = null;int len = 0;boolean lastgt = false;boolean lastlt = false;if (sum % 2 == 0) { // 偶数的时候int index2 = len2 >> 1;int index = 0;numsTemp = nums2;numsTempOr = nums1;len = len1;int medianSub1 = median - 1;for (;;) {if(numsTemp.length > 0 && index2 < numsTemp.length && index2 > -1)index = binarySearch(numsTempOr, numsTemp[index2], len, median - index2);else {numsTemp = nums1;numsTempOr = nums2;index2 = len1 >> 1;len = len2;continue;}if (index + index2 == median) {int index0 = index - 1;if(index2 == 0)return (numsTemp[index2] + numsTempOr[index0]) / 2.0;index = binarySearch(numsTempOr, numsTemp[index2 - 1], len, median - index2);if (index + index2 - 1 == medianSub1) {return (numsTemp[index2] + numsTemp[index2 - 1]) / 2.0;} else {return (numsTemp[index2] + numsTempOr[index0]) / 2.0;}} else if (index + index2 == medianSub1) {int index0 = index;if(index2 + 1 == numsTemp.length)return (numsTemp[index2] + numsTempOr[index]) / 2.0;index = binarySearch(numsTempOr, numsTemp[index2 + 1], len, medianSub1 - index2);if (index + index2 + 1 == median) {return (numsTemp[index2] + numsTemp[index2 + 1]) / 2.0;} else {return (numsTemp[index2] + numsTempOr[index0]) / 2.0;}} else if (index + index2 > median) {if (lastlt == true) {numsTemp = nums1;numsTempOr = nums2;index2 = len1 >> 1;len = len2;lastlt = false;} else {index2--;lastgt = true;}} else {if (lastgt == true) {numsTemp = nums1;numsTempOr = nums2;index2 = len1 >> 1;len = len2;lastgt = false;} else {index2++;lastlt = true;}}}} else { // 奇数的时候int index2 = len2 >> 1;int index = 0;numsTemp = nums2;numsTempOr = nums1;len = len1;for (;;) {if(numsTemp.length > 0 && index2 < numsTemp.length && index2 > -1)index = binarySearch(numsTempOr, numsTemp[index2], len, median - index2);else {numsTemp = nums1;numsTempOr = nums2;index2 = len1 >> 1;len = len2;continue;}if (index + index2 == median) {return numsTemp[index2];} else if (index + index2 > median) {if (lastlt == true) {numsTemp = nums1;numsTempOr = nums2;index2 = len1 >> 1;len = len2;lastlt = false;} else {index2--;lastgt = true;}} else {if (lastgt == true) {numsTemp = nums1;numsTempOr = nums2;index2 = len1 >> 1;len = len2;lastgt = false;} else {index2++;lastlt = true;}}}}}public static int binarySearch(int[] nums, int target, int size, int margin) { // 这个数在数组中前面有多少int begin = 0, end = size;int temp = 0;if(nums.length < 1) {return begin;}for (;;) {temp = (begin + end) >> 1;if (end > begin) {if (target > nums[temp]) {begin = temp + 1;} else if (target == nums[temp]) {if(temp == margin) return margin;while(nums[temp++] == target) {if(temp - 1 == margin) return margin; if(temp == size) {temp ++; break;}}; return --temp;} else {end = temp;}} else {return begin;}}}这是官方的代码
public static double findMedianSortedArrays2(int[] A, int[] B) { int m = A.length; int n = B.length; if (m > n) { // to ensure m<=n int[] temp = A; A = B; B = temp; int tmp = m; m = n; n = tmp; } //A是小数组 int iMin = 0, iMax = m, halfLen = (m + n + 1) >> 1; while (iMin <= iMax) { int i = (iMin + iMax) >> 1; int j = halfLen - i; if (i < iMax && B[j-1] > A[i]){ iMin++; // i is too small, j--, i++ } else if (i > iMin && B[j] < A[i-1]) { iMax--; // i is too big, j++, i-- } else { // i is perfect int maxLeft = 0; if (i == 0) { maxLeft = B[j-1]; } else if (j == 0) { maxLeft = A[i-1]; } else { maxLeft = Math.max(A[i-1], B[j-1]); } if ( (m + n) % 2 == 1 ) { return maxLeft; } int minRight = 0; if (i == m) { minRight = B[j]; } else if (j == n) { minRight = A[i]; } else { minRight = Math.min(B[j], A[i]); } return (maxLeft + minRight) / 2.0; } } return 0.0; }官方的逻辑是这样的:
首先将A数组在随机位置i处分成两部分
First let's cut A into two parts at a random position i:
left_A | right_A A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1]
因为A有m个元素,所以有m+1中分组方式(0~m)
已知:
Since A has m elements, so there are m+1 kinds of cutting (i=0∼m).
And we know:
len(left_A)=i,len(right_A)=m−i.
注意:当i=0时,left_A部分是空数组; i=m时,right_A部分是空数组;
Note: when i=0, left_A is empty, and when i=m, right_A is empty.
同理,将B在right_A随机位置j处分成两部分
With the same way, cut B into two parts at a random position j:
left_B | right_B B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
将left_A和left_B放入一个区域,同时将right_A和right_B放入另一个区域.并且将这两个区域命名为left_part 和 right_part
Put left_A and left_B into one set, and put right_A and right_B into another set. Let's name them left_partand right_part:
left_part | right_part A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1] B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
当要满足下面两个条件时
If we can ensure:
- len(left_part)=len(right_part)
- max(left_part)≤min(right_part)
我们将{A, B}两个数组里面所有的元素分成两个相同大小区域时,一个区域的值总是大于另一区域的值,推出
then we divide all elements in {A,B} into two parts with equal length, and one part is always greater than the other. Then
median=2max(left_part)+min(right_part)
满足这两个条件,只需要满足这两个条件即可:
To ensure these two conditions, we just need to ensure:
学习了
i+j=m−i+n−j (or: m−i+n−j+1)
if n≥m, we just need to set:i=0∼m, j=m+n+12−i B[j−1]≤A[i] and A[i−1]≤B[j]