LeetCode——第4题:两个排序数组的中位数

15 篇文章 0 订阅
1 篇文章 0 订阅

两个排序数组的中位数


题目:给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。

请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。

输入:nums1 = [1, 3];nums2 = [2]

输出:2.0

这道题一个比较通俗的思路是:将两个已排序的序列,遍历一次,排成一个总的序列,然后再找出其中位数。但是!这样思路的算法时间复杂度是O(m+n)并不是O( log(m+n) )
给出一个O( log(m+n) )的思路:1、找两个已排序的中位数,其实可以看成找第k个小的数字
2、由于题目要求的时间复杂度为O( log(m+n) )看到带log的时间复杂度,第一反应是二分法。
3、于是,利用下面的方法:
这里写图片描述
4、每次比较 nums1[k/2 - 1] 和 nums2[k/2 - 1] 的大小,删除较小的数列的前k/2个数字,直到k的值为1时,这时,只要比较nums1和nums2的第一个数字即可

/*
具体思路:利用二分法,每次删除前k/2个数字,直到k=1,然后比较一下nums1和nums2数组中的最小值即可
*/
class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        //sumNum为nums1和nums2的总个数和
        int sumNum = nums1.size() + nums2.size();
        //用于判断总个数是奇数还是偶数,如果是奇数,那么中位数只有1个,如果是偶数,那么中位数有2个
        bool isOdd;
        double avgNum;
        int k;
        if ((sumNum & 1) == 1){
            //奇数中的中位数是 总数/2+1
            k = sumNum / 2 + 1;
            isOdd = true;
        }
        else{
            k = sumNum / 2;
            isOdd = false;
        }
        while (k != 1){
            //这里分情况讨论,如果k/2比整个nums1都大,那么只判断nums1的最后一个数字和nums2的k/2个数即可,
            if ((k / 2)>nums1.size()){
                if (nums1.size() == 0){
                    break;
                }
                if (nums1[nums1.size() - 1]<nums2[k / 2 - 1]){
                    k = k - nums1.size();
                    nums1.clear();
                }
                else{
                    nums2.erase(nums2.begin(), nums2.begin() + k / 2);
                    k = k - (k / 2);
                }
            }
            //如果k/2比整个nums2都大,那么只判断nums2的最后一个数字和nums1的k/2个数即可,
            else if ((k / 2)>nums2.size()){
                if (nums2.size() == 0){
                    break;
                }
                if (nums2[nums2.size() - 1]<nums1[k / 2 - 1]){
                    k = k - nums2.size();
                    nums2.clear();
                }
                else{
                    nums1.erase(nums1.begin(), nums1.begin() + k / 2);
                    k = k - (k / 2);
                }
            }
            //如果nums1和nums2中个数都大于k/2,那么直接判断nums1[k/2]和nums2[k/2]即可,这里nums1[k/2-1]是因为数组是从0开始计数的
            else{
                if (nums1[k / 2 - 1] <= nums2[k / 2 - 1]){
                    nums1.erase(nums1.begin(), nums1.begin() + k / 2);
                }
                else{
                    nums2.erase(nums2.begin(), nums2.begin() + k / 2);
                }
                k = k - (k / 2);
            }
        }
        //根据奇偶来判断中位数的个数是2个还是1个
        if (isOdd){
            if (nums1.size() == 0){
                avgNum = nums2[k - 1];
            }
            else if (nums2.size() == 0){
                avgNum = nums1[k - 1];
            }
            else{
                if (nums1[k - 1]<nums2[k - 1]){
                    avgNum = nums1[k - 1];
                }
                else{
                    avgNum = nums2[k - 1];
                }
            }
        }
        else{
            if (nums1.size() == 0){
                avgNum = (nums2[k - 1] + nums2[k]) / 2.0;
            }
            else if (nums2.size() == 0){
                avgNum = (nums1[k - 1] + nums1[k]) / 2.0;
            }
            else{
                //对于偶数这边的计算要比较当心,会出现几种情况:
                //1、nums1[k-1]和nums1[k]都小于nums2[k-1],那么就取nums1[k-1]和nums1[k]的平均即可
                //2、nums2[k-1]和nums2[k]都小于nums1[k-1],那么就取nums2[k-1]和nums2[k]的平均即可
                //3、nums1[k-1]和nums2[k-1]是相对nums1[k-1]、nums1[k]、nums2[k-1]、nums2[k]这4个数字中最小的2个,那么取nums1[k-1]和nums2[k-1]的平均即可
                if (nums1[k - 1]<nums2[k - 1]){
                    if (nums1.size() - 1 >= k){
                        if (nums1[k]<nums2[k - 1]){
                            avgNum = (nums1[k - 1] + nums1[k]) / 2.0;
                        }
                        else{
                            avgNum = (nums1[k - 1] + nums2[k - 1]) / 2.0;
                        }
                    }
                    else{
                        avgNum = (nums1[k - 1] + nums2[k - 1]) / 2.0;
                    }
                }
                else{
                    if (nums2.size() - 1 >= k){
                        if (nums1[k - 1]<nums2[k]){
                            avgNum = (nums1[k - 1] + nums2[k - 1]) / 2.0;
                        }
                        else{
                            avgNum = (nums2[k - 1] + nums2[k]) / 2.0;
                        }
                    }
                    else{
                        avgNum = (nums1[k - 1] + nums2[k - 1]) / 2.0;
                    }
                }
            }
        }
        return avgNum;
    }
};
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值