算法作业第一周(leetCode)——4. Median of Two Sorted Arrays

       自从上次打完icpc省赛,我很久没有做算法题了,这还是我首次做leetCode的题。我一上来看到了这道题。这道题虽然是hard难度,一开始我以为不难,后来发现要用到二分查找第k个数。以下为题目地址:

https://leetcode.com/problems/median-of-two-sorted-arrays/description/

       这道题的大意就是给两个从小到大排序的数组,然后算这个两个数组里面所有数的中位数。其实这道题根本不需要用二分查找就能过(如果忽视O(log(m+n))的条件),只要用利用类似于归并的思想,利用两个变量指向两个数组中的数,沿着两个数组从前往后遍历。并且不断比较两个数组中数的大小,以达到从小到大遍历的效果。然后取中位数即可。这里需要分类讨论个数是奇数和偶数的情况。(后面给出了二分查找的算法)

     下面给出提交代码:

#include <bits/stdc++.h> 

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        double median, median2;
        int n1=0, n2=0, i, sum, s1, s2;
        s1 = nums1.size();
        s2 = nums2.size();
        sum = s1 + s2;
        if(sum%2)
        {
            for(i=0;i<(sum+1)/2;i++)
            {
                if(n1<s1&&(n2>=s2||nums1[n1]<nums2[n2]))
                {
                    median = nums1[n1];
                    n1++;
                }
                else
                {
                    median = nums2[n2];
                    n2++;
                }
            }
            return median;
        }
        else
        {
            for(i=0;i<sum/2+1;i++)
            {
                if(n1<s1&&(n2>=s2||nums1[n1]<nums2[n2]))
                {
                    median2 = median;
                    median = nums1[n1];
                    n1++;
                }
                else
                {
                    median2 = median;
                    median = nums2[n2];
                    n2++;
                }
            }
            return (median+median2)/2;
        }
    }
};

    代码中需要注意的是vector有可能是空的。一开始没有特别注意这一点,导致了两次RE。然后对于数组是空的情况可以通过&&和||来将后面的表达式”短路“。

if(n1<s1&&(n2>=s2||nums1[n1]<nums2[n2]))

下面给出运行结果

下面这种方法利用了二分查找,其实就是找两个数组之间第k大的数,只需要每次查询两个数组的k/2个数并比较,抛弃其中k/2个数就可以了(因为中位数不在那k个数里),然后可以通过递归解决。

#include <bits/stdc++.h> 

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int s1,s2,sum;
        s1 = nums1.size();
        s2 = nums2.size();
        sum = s1 + s2;
        //cout<<sum<<endl;
        if(sum%2)
            return findMedianSortedArraysK(nums1,nums2,0,0,(sum+1)/2);
        else
            return (findMedianSortedArraysK(nums1,nums2,0,0,sum/2+1)+findMedianSortedArraysK(nums1,nums2,0,0,sum/2))/2;
    }

    double findMedianSortedArraysK(vector<int>& nums1, vector<int>& nums2, int f1, int f2, int k)
    {
        int s1, s2;
        s1 = nums1.size();
        s2 = nums2.size();
        if(f1>=s1)
            return nums2[f2+k-1];
        if(f2>=s2)
            return nums1[f1+k-1];
        if(k==1)
            return min(nums1[f1], nums2[f2]);
        if(f1+k/2-1>=s1)
            return findMedianSortedArraysK(nums1,nums2,f1,f2+k/2,k-k/2);
        if(f2+k/2-1>=s2)
            return findMedianSortedArraysK(nums1,nums2,f1+k/2,f2,k-k/2);
        if(nums1[f1+k/2-1]<=nums2[f2+k/2-1])
            return findMedianSortedArraysK(nums1,nums2,f1+k/2,f2,k-k/2);
        else
            return findMedianSortedArraysK(nums1,nums2,f1,f2+k/2,k-k/2);
    }
};

但很奇怪的是,这个算法比上面的归并还要慢。。。我觉得可能是因为常数项太大(递归比循环慢),以及测试样例不够大。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值