Leetcode刷题笔记 Day2 (热题100 using C++)

T4 寻找两个正序数组的中位数

链接: link

思路1: 暴力解法:直接将两个数组合并,得到中位数
class Solution {
public:
    int MAXN=1e7;
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        //思路1: 暴力解法:直接将两个数组合并,得到中位数
        double ans;
        int n1=nums1.size(),n2=nums2.size();
        if(!n1){
            if(n2%2){
                return nums2[n2/2]; 
            }
            else{
                return (nums2[n2/2]+nums2[n2/2-1])/2.0;
            }
        }
        if(!n2){
            if(n1%2){
                return nums1[n1/2]; 
            }
            else{
                return (nums1[n1/2]+nums1[n1/2-1])/2.0;
            }
        }
        int nums[n1+n2];
        for(int i=0,j=0,k=0;i<n1 || j<n2;){
            int temp1=(i<n1?nums1[i]:MAXN);
            int temp2=(j<n2?nums2[j]:MAXN);
            if(temp1<temp2){
                nums[k++]=temp1;
                i++;
            }
            else{
                nums[k++]=temp2;
                j++;
            }
        }
        int n=n1+n2;
        if(n%2){
            return nums[n/2];
        }
        else{
            return (nums[n/2]+nums[n/2-1])/2.0;
        }
    }
};

实际上此种思路不需要将两个数组完全合并,当k满足大于(n1+n2)/2即可中止,根据n的奇偶返回中位数即可,可以将复杂度降低一半左右。

思路2:不进行合并,直接利用两数组有序,进行中位数查找(减少空间复杂度,并利用二分查找降低时间复杂度)

大致思路:假定需要查询的为第k小数,则每次舍去k/2个数(更新k,k是不断除2,避免误解)。用a,b分别记录两个数组还未舍去的头部指针,每次比较nums1[a+k/2]和nums2[b+k/2],更新较小的数组的头部指针,直至k=1或某个数组遍历完。
需要注意的是,当总数为偶数时,中位数为两个数的平均值,
具体参考:(链接) link中的方法一,里面的图解还是挺清晰的

class Solution {
public:
    int findkth(vector<int>& nums1, vector<int>& nums2, int k){
        int m=nums1.size(),n=nums2.size();
        int a=0, b=0;
        while(1){
            if(a==m){
                return nums2[b+k-1];
            }
            if(b==n){
                return nums1[a+k-1];
            }
            if(k==1){
                return min(nums1[a],nums2[b]);
            }
            int index1=min(a+k/2-1,m-1);
            int index2=min(b+k/2-1,n-1);
            if(nums1[index1]<nums2[index2]){
                k-=index1-a+1;
                a=index1+1;
            }
            else{
                k-=index2-b+1;
                b=index2+1;
            }
        }
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        //思路2: 二分查找
        int k=nums1.size()+nums2.size();   
        if(k%2){        //奇数
            return findkth(nums1,nums2,k/2+1)*1.0;
        }      
        else{
            return (findkth(nums1,nums2,k/2)+findkth(nums1,nums2,k/2+1))/2.0;
        }
    }
};
官方还给了一个时间复杂度更小的算法,看了一下大致思路就是利用对中位数的理解:将一个集合划分为两个长度相等的子集,其中一个子集中的元素总是大于另一个子集中的元素。即max(left_part)<=min(right_part)&&len(left_part)=len(right_part),则median分奇偶可以快速求出。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值