题目:https://leetcode.com/problems/median-of-two-sorted-arrays/#/description
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分析 :
这道题的难点在于实现如何才能简洁。这是个二次二分的题,开始我只想到在nums1中二分,找到数nums1[mid1]后,找在nums2中的位置,再判断是否找到。这样,就需要在nums1和nums2上同时二分,再加上越界的判断问题,实现起来就比较困难。
后来看了stellari 的solution,确实是很巧妙的方法,用特殊的方法表示了分隔符,把奇偶的情况合二为一,且巧妙地处理了数组越界。下面简述一个他的方法,如有什么不清楚的,请看原文链接
首先,可以把奇数和偶数的情况合二为一,如 [2 3 4 5 6],我们可以这样分隔[2 3 (4/4) 5 7]
设斜杠左右的索引为L,R,那么 L = (N-1)/2, R = N/2
A[mid] = (A[(N-1)/2] + A[N/2])/2
现在为了表示斜杠,我们在数字间插入#
A1: [# 1 # 2 # 3 # 4 # 5 #] (N1 = 5, N1_positions = 11)
A2: [# 1 # 1 # 1 # 1 #] (N2 = 4, N2_positions = 9)
可以推出index(L) = (CutPosition-1)/2, index(R) = (CutPosition)/2
如果A2的插入位是C2,那么C1 = N1 + N2 - k,所以只需要二分一个,另一个就能求到,时间复杂度为O(log(min(n1,n2))
L1 = A1[(C1-1)/2]; R1 = A1[C1/2];
L2 = A2[(C2-1)/2]; R2 = A2[C2/2];
L1为A1插入符左边的数,R1为A1插入符后边的数并且它们需要满足
L1 <= R1 && L1 <= R2&& L2 <= R1 && L2 <= R2
Java实现:
public double findMedianSortedArrays(int[] nums1, int[] nums2)
{
int n1 = nums1.length;
int n2 = nums2.length;
if(n2>n1) return findMedianSortedArrays(nums2, nums1);
if(n2==0) return (nums1[(n1-1)/2]+nums1[n1/2])/2.0;
int lo=0, hi=n2*2;
while(lo<=hi)
{
int mid2 = (lo+hi)/2;
int mid1 = n1+n2-mid2;
int l1 = (mid1==0)? Integer.MIN_VALUE: nums1[(mid1-1)/2];//处理数组越界的情况
int r1 = (mid1==2*n1)? Integer.MAX_VALUE: nums1[mid1/2];
int l2 = (mid2==0)? Integer.MIN_VALUE: nums2[(mid2-1)/2];
int r2 = (mid2==2*n2)? Integer.MAX_VALUE: nums2[mid2/2];
if(l1>r2)
lo = mid2+1;
else if(l2>r1)
hi = mid2-1;
else
return ((double)Integer.max(l1, l2)+(double)Integer.min(r1, r2))/2;
}
return -1;
}