4. Median of Two Sorted Arrays

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

这题是个一目了然的题目,可是最优解并不容易想到。

方法一:O(nlogn)

直接将俩数列合并,首尾相接,排序,然后判断奇偶性,返回中位数。复杂度就是在于排序的复杂度。

方法二:O(n)

类似于insertion sort,将俩数列逐一判断合并成一个排序好的数列,返回中位数。这里为了保持in place,我们直接数对应中位数的个数,这样写起来相对复杂,没有构建一个新数组来的方便。

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    int m = nums1.size();
    int n = nums2.size();
    int i, j, count = 0, flag;
    double res, temp;
    // flag判断奇偶性
    if ((m + n) % 2 == 0) flag = 0;
    else flag = 1;
    if (flag == 1) {
        //考虑一个为空数组的情况
        if (m == 0) {
            res = nums2[n/2];
            return res;
        }
        if (n == 0) {
            res = nums1[m/2];
            return res;
        }
        //注意考虑数组越界的情况,当一个数组数完后的循环情况
        for (i = 0, j = 0; ; ) {
            if ((i < m && nums1[i] < nums2[j]) || j >= n) {
                res = nums1[i];
                i++;
                count++;
            }
            else {
                res = nums2[j];
                j++;
                count++;
            }
            if (count == (m+n)/2 + 1) {
                return res;
            }
        }
    }
    else {
        if (m == 0) {
            res = nums2[n/2-1];
            res += nums2[n/2];
            return res/2;
        }
        if (n == 0) {
            res = nums1[m/2-1];
            res += nums1[m/2];
            return res/2;
        }
        for (i = 0, j = 0; ;) {
            if ((i < m && nums1[i] < nums2[j]) || j >= n) {
                res = nums1[i];
                i++;
                count++;
            }
            else {
                res = nums2[j];
                j++;
                count++;
            }
            if (count == (m+n)/2) {
                temp = res;
            }
            if (count == (m+n)/2 + 1) {
                res = (res+temp)/2;
                return res;
            }
        }
    }
}
方法三:O(log(m+n))

当复杂度降到log基本就是每次判断减少一半的意思。二分法那种意思。这题可以对接到找两个排序好数组的第K小元素。将问题分为两部分,第一部分是基于这个问题,将总数分奇偶,给出不同的第K小情况。第二部分就是对于给出的K,进行递归选择。
递归的基本思路就是,假设两数组长度都大于K/2,判断两组里第K/2个元素的大小,假设A[K/2-1]小于B[K/2-1],那么可以认为第K大肯定没有A数组的事,所以一次判断后减少一半,直接再去B中找第K/2小的数。如果A[K/2-1]大于B[K/2-1],B的这一半就可以放弃,问题在A中直接找。如果相等,直接返回A[K/2-1]。如果A的长度不够K/2,直接减少B中的K/2长度,然后再判断剩下的A和B以及对应的要找的第几小数,因为此时,不论A中不够长度的那几个数是大是小,都不够K的长度,所以第K小的数,前面必然大部分需要B来填充,我们只用比较A和B中后几位的数,第K小一定是从这里面产生。
代码如下:

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
   int total = nums1.size() + nums2.size();
   if (total & 1) {
       return findKth(nums1, nums2, 0, 0, total/2+1);
   }
   else {
       return (findKth(nums1, nums2, 0, 0, total/2) + findKth(nums1, nums2, 0, 0, total/2+1))/2.0;
   }
}
double findKth(vector<int> &A, vector<int> &B, int A_st, int B_st, int K) {
    if (A_st >= A.size()) return B[B_st + K - 1];
    if (B_st >= B.size()) return A[A_st + K - 1];
    if (K == 1) return min(A[A_st], B[B_st]);
    int A_key = A_st + K/2 - 1 >= A.size() ? INT_MAX : A[A_st + K/2 - 1];
    int B_key = B_st + K/2 - 1 >= B.size() ? INT_MAX : B[B_st + K/2 - 1];
    if (A_key < B_key) {
        return findKth(A, B, A_st+K/2, B_st, K-K/2);
    }
    else {
        return findKth(A, B, A_st, B_st+K/2, K-K/2);
    }
}

这题的思路可以记住,如何在两个sorted array中寻找第K大或者小的数。每次判断减少一半的思路很重要。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值