【Leetcode】4. 寻找两个有序数组的中位数 【二分】

给定两个大小为 m m m n n n 的有序数组 n u m s 1 nums1 nums1 n u m s 2 nums2 nums2

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O ( l o g ( m + n ) ) O(log(m + n)) O(log(m+n))

你可以假设 n u m s 1 nums1 nums1 n u m s 2 nums2 nums2 不会同时为空。

示例 1 1 1:

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0

示例 2 2 2:

nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

1 1 1:将两个有序数组合并为一个新有序数组(只需取一半的值 + 1即可计算中位数),先判断该有序数组个数的奇偶,然后根据奇偶计算其中位数

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size();
        vector<int> num;
        int len = (m + n) / 2 + 1;
        int j = 0, k = 0;
        //合并两个有序数组:取一半+1的元素值即可计算中位数
        for (int i = 1; i <= len; ++i) {
            if (j < m && k < n && nums1[j] < nums2[k]) 
                num.push_back(nums1[j++]);
            if (j < m && k < n && nums1[j] >= nums2[k])
                num.push_back(nums2[k++]);
            if (j == m && k < n) {
                num.push_back(nums2[k++]);
            }
            if (k == n && j < m) {
                num.push_back(nums1[j++]);
            }
        }
        if ((m + n) % 2 == 0) {
            return (double)(num[len - 2] + num[len - 1])/2;
        }
        else
            return (double)(num[len - 1]);
    }
};

2 2 2:【二分法】参考4. 寻找两个有序数组的中位数 C / C++

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        
        if (m > n) {   //保证nums1元素个数少,便于二分
            return findMedianSortedArrays(nums2, nums1);
        }
        
        int lMax1, lMax2, rMin1, rMin2, l0 = 0, r0 = 2 * m;
        while (l0 <= r0) {
            int c1 = (l0 + r0) / 2;
            int c2 = m + n - c1;
            
            //c1 = 0,说明元素都在右边,lMax1取INT_MIN,否则计算其位置
            lMax1 = (c1 == 0) ? INT_MIN : (nums1[(c1 - 1) / 2]);   
            //c1 = 2*n, 说明元素都在左边,rMin1取INT_MAX,否则计算其位置
            rMin1 = (c1 == 2 * m) ? INT_MAX : (nums1[c1 / 2]);
            //同c1
            lMax2 = (c2 == 0) ? INT_MIN : (nums2[(c2 - 1) / 2]);
            rMin2 = (c2 == 2 * n) ? INT_MAX : (nums2[c2 / 2]);
            
            //lMax1大于rMin2,说明左边元素过多,向左二分
            if (lMax1 > rMin2)  r0 = c1 - 1;
            //lMax2大于rMin1,右边元素过多,向右二分
            else if (lMax2 > rMin1) l0 = c1 + 1;
            //相等则满足条件,退出循环计算中位数
            else   break;
        }
        
        return (max(lMax1, lMax2) + min(rMin1, rMin2)) / 2.0;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值