LeetCode4. Median of Two Sorted Arrays(二分法)

题解

划分元素组

长数组a,短数组b

数组 元素组1 元素组2
a(长度为m) a1,a2,a3...ai ai+1,ai+2...am-1,am
b(长度为n) b1,b2,b3...bj bj+1,bj+2...bn-1,bn

划分保证元素组1中元素一定小于等于元素组2中的元素,且size(元素组1)-size(元素组2)的绝对值最小。

  1. 若m+n为偶数,划分之后size(元素组1)==size(元素组2)。则中位数一定是ai,ai+1,bj,bj+1这四个数中两个数的平均数。
  2. 若m+n为奇数,划分之后size(元素组1)+1==size(元素组2)。则中位数一定是ai,ai+1,bj,bj+1这四个数中的一个。

如何划分数组

  1. 划分长数组,因为长数组中的元素能定位短数组中的不同元素(也可能定位不到),而短数组定位长数组中的元素是受限的。
  2. 根据长数组元素定位短数组元素。
    考虑如下情况。
    短数组a = {3};
    长数组b = {1,2,4,5,6};
    若用短数组去定位长数组,则a0总是定位到b3(下标=(m+n)/2-0=3,采用不同的计算方法可以得到不同的下标),而b3=5,显然不是中位数。

确定中位数的值

  1. 若m+n为偶数,则ans = (max(ai,bj)+min(ai+1,bj+1))/2;
  2. 若m+n为奇数,由于元素组2比元素组1个数多一个,中位数一定存在于ai+1,bj+1,则ans = min(ai+1,bj+1);

Code

class Solution {
public:
    double findMedianSortedArrays(vector<int>& a, vector<int>& b) {
        // m,n表示两vector数组的大小。
        int m = a.size();
        int n = b.size();
        // 若a数组长度小于b数组,则交换两数组。因为我们要根据长数组元素定位短数组中的对应元素
        if(m < n) return findMedianSortedArrays(b,a);
        int l = 0, r = m;
        double ans;
        int mid1, mid2,left1,left2,right1,right2;
	    while (l < r) {
	        // mid1为二分数组a,mid2对应mid1取值
		    mid1 = (l + r) / 2;
		    mid2 = (m + n) / 2 - mid1;
            
            // 如果mid2越界,调整l和r,重新确定mid1。
            if(mid2 < 0){
                r = mid1;
                continue;
            }
            if(mid2 > n){
                l = mid1+1;
                continue;
            }
            // 取出a[i]、a[i+1]、b[j]、b[j+1]。左边越界,设为最小值;右边越界,设为最大值。
		    left1 = mid1 - 1 <= -1 ? INT_MIN : a[mid1 - 1];
		    right1 = mid1 >= m ? INT_MAX : a[mid1];
		    left2 = mid2 - 1 <= -1 ? INT_MIN : b[mid2 - 1];
		    right2 = mid2 >= n ? INT_MAX : b[mid2];

            // 如果满足左边元素组小于等于右边元素组,跳出循环
		    if (right1 >= left2 && left1 <= right2) {
			    break;
		    }
		    // 如果不满足,则调整l,r重新取mid1。
		    if (right1 < left2) {
			    l = mid1+1;
		    }
		    if (left1 > right2) {
			    r = mid1;
		    }
	    }
	    //如果为奇数
        if (1 & (m + n)) {
            ans = 1.0*min(right1, right2);
	    }
	    else {
	        ans = 1.0*(max(left1, left2) + min(right1, right2)) / 2;
        }
        return ans;
    }
};
posted @ 2020-07-09 09:11  ninding  阅读(165)  评论(0编辑  收藏  举报