[leetcode][4]Median of Two Sorted Arrays

Problem

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

Solution

寻找2个有序数组的中位数,假设数组A和数组B的长度分别为m和n,最简单的办法是用两个指针分别指向2个数组的头,依次比较,将数值更小的数组指针向前移动,比较(m+n+1)/2次后即可得到结果,这一算法的时间复杂度是O(m+n),在答案区看到了一个更巧妙的解法。

    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]

我们总使得A的长度m小于等于B的长度n,因此如果刚开始给的A和B长度不满足m<=n,则用B替代A,A替代B。如果找到A数组和B数组的合理分隔点,即可以得到两个数组的中位数。假设A和B的分隔点分别是i和j,则满足以下2个条件:

① left_part和right_part的长度相同或差1
如果m+n是偶数,则
    i + j = m - i + n - j
如果m+n是奇数,则(这种情况下我们使左边比右边多1)
    i + j = m - i + n - j + 1
综合2种情况, j = (m + n + 1)/2 - i

② left_part的数全部不大于right_part的数,即max(left_part) <= min(right_part)
B[j-1] <= A[i] and A[i-1] <= B[j]

现在问题转化为:i从0到m中,找到一个符合条件的i使得B[j-1] <= A[i] and A[i-1] <= B[j], j = (m + n + 1)/2 - i,很显然在排序数组中可以用二分查找法

imin = 0, imax = m
i = (imin + imax)/2, j = (m + n + 1)/2 - i
while (imin <= imax) {
    ①if (B[j-1] <= A[i] and A[i-1] <= B[j])
        找到了i
    ②if (B[j - 1] > A[i])
        说明i找的过小,imin = i + 1if (A[i - 1] > B[j])
        说明i找的过大,imax = i - 1 
}

边界条件说明:
i = 0, i = m, j = 0, j = n是边界情况,在二分查找过程中要做一定限制。
在情况②中,设定i < m ==> j = (m+n+1)/2 - i > (m+n+1)/2 - m >= (2*m+1)/2 - m >= 0
在情况③中,设定i > 0 ==> j = (m+n+1)/2 - i < (m+n+1)/2 <= (2*n+1)/2 <= n

综上,这种解法的时间复杂度是O(log(min(m,n)))。

public class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {    
        int m = nums1.length;
        int n = nums2.length;
        if(m>n) return findMedianSortedArrays(nums2,nums1);
        //for all the following, we assumed m<=n;
        int imin = 0;
        int imax = m;
        int max_of_left;
        int min_of_right;
        int i=(imin+imax)/2, j=(m+n+1)/2 -i;
        while(imin <= imax){
            i=(imin+imax)/2;
            j = (m+n+1)/2 -i;
            if(i>0 && nums1[i-1] > nums2[j]){
                imax = i-1;
            }else if(i < m  && nums2[j-1] > nums1[i]){      
                imin = i+1;
            }else break;
        }

        if(i == 0) max_of_left = nums2[j-1];    
        else if(j == 0) max_of_left = nums1[i-1];
        else  max_of_left = Math.max(nums1[i-1],nums2[j-1]);
        if((m + n) % 2 == 1) return max_of_left;

        if(i == m) min_of_right = nums2[j];
        else if( j == n) min_of_right = nums1[i];
        else min_of_right = Math.min(nums1[i],nums2[j]);

        return (max_of_left+min_of_right)/2.0;
 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值