Leetcode解题笔记 4.Median of Two Sorted Arrays [Hard]

来源:互联网 发布:c语言次方怎么写 编辑:程序博客网 时间:2024/06/03 17:47

解题思路

以下解题步骤引用自leetcode讨论里MissMary的回答
要解决这个问题,首先我们要明白median的意义,在集合中,midean将一个集合分为两个长度相等的子集,其中小的一半的最大值要小于或等于大的一半。
问题给出两个集合,我们可以将这两个集合分为左右两部分。
对于集合A:

left_A                   |        right_AA[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]

对于集合B:

left_B                   |        right_BB[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

两个集合联系在一起来看:

left_part                |        right_partA[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]

所以如果我们可以调整i,j使得

1) len(left_part) == len(right_part)     or len(left_part) + 1 == len(right_part) (考虑长度奇偶性)2) max(left_part) <= min(right_part)

则可以保证将AB两个集合分成相等的两半 ,其中左半边最大值要小于右半边。
为了保证上述的条件,我们需要保证

(1) 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 + 1)/2 - i(2) B[j-1] <= A[i] and A[i-1] <= B[j]

这里我们一开始直接设

imin = 0, imax = mi = (imin + imax)/2, j = (m + n + 1)/2 - i

以下是个人理解:
其实相当于一个风车,当前状态若达不到满足条件的要求,则转动风车叶,如图所示
一开始:
这里写图片描述
若不符合条件:
则根据情况改变imax,imin改变i, 而j与i相关所以不会破坏左右两边相等的条件
这里写图片描述
而不符合的情况可以分为以下几种:

 <a> B[j-1] <= A[i] and A[i-1] <= B[j]     Means we have found the object `i`, so stop searching. <b> B[j-1] > A[i]     Means A[i] is too small. We must `ajust` i to get `B[j-1] <= A[i]`. <c> A[i-1] > B[j]     Means A[i-1] is too big. And we must `decrease` i to get `A[i-1]<=B[j]`.

当i找到,我们就能计算出中值为:

max(A[i-1], B[j-1]) (when m + n is odd)or (max(A[i-1], B[j-1]) + min(A[i], B[j]))/2 (when m + n is even)

关于边界 ,只要到达边界停止判断两个集合的交叉大小比即可,但记得把判断写在前面,以防越界访问。

代码:

class Solution {public:    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {        int m, n, i, j;        int imin, imax, halfPoint;        double maxOfLeft, minOfRight;        //保证nums1长度短于nums2          if (nums1.size() > nums2.size()) {            vector<int> tem_v(nums1);            nums1 = nums2;            nums2 = tem_v;        }        m = nums1.size();        n = nums2.size();        imin = 0;        imax = m;        while (imin <= imax) {            i = imin + imax / 2;            j = (m + n + 1)/2 - i;            if (i > 0 && nums1[i - 1] > nums2[j]) {                imax--;            } else if (i < m && nums2[j - 1] >  nums1[i]) {                imin++;            } else {                if (i == 0) maxOfLeft = nums2[j - 1];                else if (j == 0) maxOfLeft = nums1[i - 1];                else maxOfLeft = max(nums1[i-1], nums2[j-1]);                if ((m + n) % 2 == 1) return maxOfLeft;                if (i == m) minOfRight = nums2[j];                else if (j == n) minOfRight = nums1[i];                else minOfRight = min(nums1[i], nums2[j]);                return (minOfRight + maxOfLeft) / 2;            }                 }        return 0;    }};

复杂度:
O(log(min(m,n))