leetcode 4.median of two sorted arrays

(可忽略中间直接跳到最后一段的代码)

写在前面的废话
小渣渣的leetcode之旅
刚拿到这道题第一个是想到用类似归并的算法逐个逐个数,然后找到中间的数,不过觉得既然是标为hard的题觉得这种做法时间发咋度较高。然后产生了第二个想法,就是在数组1和数组2都找中间数num1[p1],num2[p2],然后比较两者,再慢慢比较两者,通过挪动p1和p2最终找到两者数组的中间数。无奈这种方法考虑的情况比较多,最终以失败告终。于是,还是上网学习了一下别人的代码,找到了一种比价容易实现好理解的方法,就是将找中间数转化为找第k大的数

基本思路是:在num1和num2中找到p1和p2(两者及其前面的数加起来共k个),然后比较num1[p1]和num2[p2],假设num1[p1] < num2[p2],则删去num1前p1个数,改为寻找两个数组的第k-p1大的数,以此类推,递归函数。

注意边界情况:其中一个数组为空的话则返回另一个数组的第k大值。
代码如下:

#include<iostream>
#include<vector>
using namespace std;

double findKth(vector<int> n1, int size1, vector<int> n2, int size2, int k){
    if (size1 < size2) //把数组1定为两者中较大者可以简化程序
        return findKth(n2, size2, n1, size1, k);
    if (size2 == 0)//其中一个数组为空的情况,直接返回另一数组第k大值
        return n1[k - 1];
    if (k == 1)//由于p1和p2及其前面的数加起来至少有2个,所以需要将1个的情况分开讨论
    { 
    if (!size1) return n2[0];
    if (!size2) return n1[0];
    return min(n1[0],n2[0]);
}
    int mid2 = min(k/2,size2); int mid1 = k - mid2;//分配p1、p2,写的时候用的是mid1 = p1-1、mid2 =p2-1
    mid1--;
    mid2--;

    if (n1[mid1] > n2[mid2])
    {
        if (mid2 + 1 == size2) return findKth(n1, size1, n2, 0 , k - mid2 - 1);//不单独讨论该情况的话,传n2数组会因为越界报错
        vector<int> v(n2.begin()+mid2+1,n2.end());
        return findKth(n1, size1, v,size2 - mid2 - 1, k - mid2 - 1);
    }
    else if (n1[mid1] < n2[mid2])
    {
        if (mid1 + 1 == size1) return findKth(n1, 0, n2, size2 , k - mid1 - 1);
        vector<int> v(n1.begin()+mid1+1,n1.end());
        return findKth(v, size1 - mid1 - 1, n2, size2, k - mid1 - 1);
    }

    else return n1[mid1];//两者相等,则n1[mid1] = n2[mid2],其大小恰好为第k个值的大小

} 

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int size1 = nums1.size();
        int size2 = nums2.size();
        int kk = (size1+size2)/2+1;
        if ((size1 + size2)%2 == 1)
        return findKth(nums1,nums1.size(),nums2,nums2.size(),kk);//两个数组总数为奇数
        else {
            double a =findKth(nums1,nums1.size(),nums2,nums2.size(),kk-1);
            double b =findKth(nums1,nums1.size(),nums2,nums2.size(),kk);
            return (a+b)/2;//两个数组总数为偶数
    }
}
};

int main(){
    vector<int> n1;
    vector<int> n2;
    n1.push_back(3);
    n1.push_back(4);
    n2.push_back(1);
    n2.push_back(2);
    Solution s1;
    cout << s1.findMedianSortedArrays(n1,n2);
    return 0;
}

之前真有点啰嗦。有空再整理整理。

class Solution {
public:
    double findK(vector<int>& nums1,int start1,vector<int>& nums2,int start2,int k)
    {
        if (start1 >= nums1.size()) return nums2[start2+k-1];
        if (start2 >= nums2.size()) return nums1[start1+k-1];
        if (k == 1) return min(nums1[start1],nums2[start2]);
        int s1 = start1 + (k>>1) , s2 = start2 + (k>>1) ;
        s1 = s1 >= nums1.size() ? nums1.size() : s1;
        s2 = s2 >= nums2.size() ? nums2.size() : s2;
        if (nums1[s1-1] <= nums2[s2-1])
            return findK(nums1,s1,nums2,start2,k - (s1 - start1));
        else return findK(nums1,start1,nums2,s2,k - (s2 - start2));
    }

    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) 
    {
       int size1 = nums1.size(),size2= nums2.size();
       if ((size1 + size2) & 1)
           return findK(nums1,0,nums2,0,((size1+size2)>>1)+1);
        else return (findK(nums1,0,nums2,0,((size1+size2)>>1)+1)+findK(nums1,0,nums2,0,(size1+size2)>>1))/2.0;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值