力扣练习题 寻找两个正序数组中的中位数

解题思路:

  • 合并数组,定位中位数;
  • 二分查找;
  • 公式推导(真的秀,参见官方回答)。

思路一 合并数组

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m=nums1.size();
        int n=nums2.size();
        int len=m+n;
        double sum[len];
        int ans1=0,ans2=0;
        for(int i=0;i<len;++i)
        {
            
            if(ans1<m&&ans2<n)
            {
                if(nums1[ans1]<=nums2[ans2])
            {
                sum[i]=nums1[ans1];
                ans1++;
                continue;
            }else
            {
                sum[i]=nums2[ans2];
                ans2++;
                continue;
            }
            }
            if(ans1==m&&ans2<n)
            {
                sum[i]=nums2[ans2];
                ans2++;
                continue;
            }
            if(ans1<m&&ans2==n)
            {
                sum[i]=nums1[ans1];
                ans1++;
                continue;
            }
            
        }
        double res=0;
        if(len%2==0)
        {
            res=(sum[len/2-1]+sum[len/2])/2;
        }else{
            res=sum[len/2];
        }
        return res;
        
        
    }
};

这是我能独立写出来的解法,复杂度如下:

时间复杂度空间复杂度
O(m+n)O(m+n)

思路二 二分查找

nums1长度为m,nums2长度为n,查找中位数,可以转化为查找两个数组中第k大的数:

(1)数组长度为奇数:k=(m+n)/2+1;

(2)数组长度为偶数 :k=(m+n)/2,(m+n)/2+1,中位数为这两者的平均值。

可以采用二分查找的思想:

-->寻找两个数组中第k大的数:

有三种情况:

(1)nums1[k/2-1]<nums2[k/2-1]:可以排除num1[0]-nums1[k/2-1]的数;

(2)nums1[k/2-1]>nums2[k/2-1]:可以排除num2[0]-nums2[k/2-1]的数;

(3)nums1[k/2-1]=nums2[k/2-1]:可以按照(1)的方式处理。

特殊情况处理:

(1)越界;取该数组最后一位;

(2)其中一者为空;

(3)k=1;取头部较小的;

代码如下 :

class Solution {
public:
    double findKthElenment(vector<int>&nums1,vector<int>&nums2,int k){
        int m=nums1.size();
        int n=nums2.size();
        int ans1=0,ans2=0;

        while(true)
        {
            if(ans1==m)
            {
                return nums2[ans2+k-1];
            }
            if(ans2==n)
            {
                return nums1[ans1+k-1];

            }
            if(k==1)
            {
                return min(nums1[ans1],nums2[ans2]);
            }

            int newans1=min(ans1+k/2-1,m-1);
            int newans2=min(ans2+k/2-1,n-1);
            if(nums1[newans1]<=nums2[newans2])
            {
                k-=newans1-ans1+1;
                ans1=newans1+1;
            }else
            {
                k-=newans2-ans2+1;
                ans2=newans2+1;
            }


        }

    }

    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m=nums1.size();
        int n=nums2.size();
        if((m+n)%2!=0)
        {
            return findKthElenment(nums1,nums2,(m+n)/2+1);
        }
        else{
            return (findKthElenment(nums1,nums2, (m+n)/2)+findKthElenment(nums1, nums2, (m+n)/2+1))/2;
        }


    }
};

这种方法我感觉我理解得还有些磕磕绊绊,复杂度如下:

时间复杂度空间复杂度
O(log(m+n))O(1)

思路三 划分数组 公式推导

存在规律可以推导,自认为通用性不大,就不深究了。

参考链接:寻找两个有序数组的中位数 - 寻找两个正序数组的中位数 - 力扣(LeetCode)

复杂度为:

时间复杂度空间复杂度
O(m+n)O(m+n)

思考总结:总体思路不难,但是边界情况和分类情况较多:奇偶分类、一个数组遍历完这些...一个个拎出来讲会很麻烦,如果思路不够清晰的话,很容易就绕进去,而且写出很多的bug。

所以最好先列出大致思路和分类情况再开始写代码,边想边写会出乱子。

像找中位数转化为查找第k大数这样转化抽象思维,还需要强化练习。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值