【算法】【Divide and conquer】Median of Two Sorted Arrays

Difficulty:Hard

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

Solution

思路

该题目的解决思路和代码都有给出:
https://leetcode.com/problems/median-of-two-sorted-arrays/solution/

这里主要说说做题时我遇到的问题和难点。

我利用二分法,先设好iminimax的值,令 i=imin+imax2 . 若i偏大了,则令imax= i - 1, 再令 i=imin+imax2 .
但这样的结果是超时的。看过Solution的Java代码,原来在i偏大时,他令imax = imax - 1, 再令 i=imin+imax2 . 这样不超时。
后者比前者快的原因暂不清楚,没有研究过testcase。

掌握好解题的大致思路后,我认为尚存的难点是边界问题和访问过界,即在i = 0时不能访问nums1[i - 1], 在i = m时不能访问nums1[i]. 这些问题看似简单,但在解决这些问题时总是容易顾此失彼。

代码

Accepted. 52ms. Beats 67% of cpp submissions.

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        if (nums1.size() > nums2.size()) nums1.swap(nums2);
        int m = nums1.size(), n = nums2.size();
        int imin = 0, imax = m, halflen = (m + n + 1) / 2;
        int i, j;

        while (imin <= imax) {
            // 这里保证左右两边数量相等
            // 即len(nums1[0~i-1])+len(nums2[0~j-1]) == len(nums1[i~m-1])+len(nums2[j~n-1])
            i = (imin + imax) / 2;
            j = halflen - i;

            // 要想找到中位数,
            // 只要满足nums1[i-1] <= nums2[j] && nums2[j-1] <= nums1[i]两个条件即可.
            // 若nums1[i-1] > nums2[j], 说明i太大,要减小它.
            // 若nums2[j-1] > nums1[i], 说明i太小,要增大它.
            // 遇到边界时,
            // 对于nums1[i-1] <= nums2[j], 若i == 0, 说明nums1左半部分是空的,
            // 则不需要比较它们.
            // 同理对于nums2[j-1] <= nums1[i], 若i == m, 说明nums1右半部分是空的,不需比较它们.
            // 由于前面已保证m <= n, 故访问nums2[j]时不会越界, 不需考虑j == 0或n的情况.
            if (i != 0 && nums1[i - 1] > nums2[j]) {  // i太大,要减小i
                --imax;
            }
            else if (i != m && nums2[j - 1] > nums1[i]) {  // i太小,要增大i
                ++imin;
            }
            else {  // i is perfect, 计算中位数
                int leftmax, rightmin;

                if (i == 0) leftmax = nums2[j - 1];
                else if (j == 0) leftmax = nums1[i - 1];
                else leftmax = nums1[i - 1] >= nums2[j - 1] ? nums1[i - 1] : nums2[j - 1];

                if (i == m) rightmin = nums2[j];
                else if (j == n) rightmin = nums1[i];
                else rightmin = nums1[i] < nums2[j] ? nums1[i] : nums2[j];

                if ((m + n) % 2 == 1) return leftmax;
                else return (double(leftmax) + double(rightmin)) / double(2);
            }
        }
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值