自己做Leetcode|5.寻找两个有序数组的中位数

emmm没做出来,太菜了我。换个封面。

 

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。你可以假设 nums1 和 nums2 不会同时为空。

 

示例 1:

nums1 = [1, 3]

nums2 = [2]

则中位数是 2.0

 

示例 2:

nums1 = [1, 2]

nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

 

合并有序数组自然可以,但是复杂度就超了。看到这个复杂度要求,想到的是二分。然后就没了。接着就哀嚎自己菜啊。

 

下面是搬运解题思路大佬的

 

其实二分思想就是从数组的两边夹逼或排除,由循环不变式可知循环返回的那个位置就是满足查找条件(比如插入的位置)的位置。

a数组长度为n,b数组长度为m;

首先,找a和b两个有序数组中第K小,就是在a中找某个位置i,在b中找某个位置j,其满足条件为:

1、i+j=k

2、a[i-1]<=b[j]&&b[j-1]<=a[i]

这样第K小即为:max(a[i-1],b[j-1]);

其次,我们就可以在a数组中二分查找位置i,相应b中位置j=k-i,但是要注意b中j的位置不能越过b的边界即:0<=j<=m,

这样可以得到在a数组中二分查找的范围:0<=i<=n且k-m<=i<=k即max(0,k-m)<=i<=min(k,n);

我们可以在这个范围内用二分模板查找i的位置。

最后,二分找到i即代码中的le后,注意边界判断如果位置i和j前面都有元素,第k小=max(a[i-1],b[j-1]);如果i=0,

第k小=b[j-1];如果j=0;第k小=a[i-1];

两个有序数组的中位数即为:1、两个数组长度(m+n)为奇数,求第(m+n)/2+1小元素;2、两个数组长度(m+n)为偶数,求

第(m+n)/2小、第(m+n)/2+1小,两者平均值。

自己做Leetcode|5.寻找两个有序数组的中位数_第1张图片

 

作者:nojoker

链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/jiang-qi-zhuan-wei-zhao-liang-ge-you-xu-shu-zu-de-/

 

C艹代码:

class Solution {public:int findKthElm(vector& nums1,vector& nums2,int k){        assert(1<=k&&k<=nums1.size()+nums2.size());int le=max(0,int(k-nums2.size())),ri=min(k,int(nums1.size()));while(leint m=le+(ri-le)/2;if(nums2[k-m-1]>nums1[m]) le=m+1;else ri=m;        }//循环结束时的位置le即为所求位置,第k小即为max(nums1[le-1]),nums2[k-le-1]),但是由于le可以为0、k,所以//le-1或者k-le-1可能不存在所以下面单独判断下int nums1LeftMax=le==0?INT_MIN:nums1[le-1];int nums2LeftMax=le==k?INT_MIN:nums2[k-le-1];return max(nums1LeftMax,nums2LeftMax);    }double findMedianSortedArrays(vector& nums1, vector& nums2) {int n=nums1.size()+nums2.size();if(n&1){//两个数组长度和为奇数return findKthElm(nums1,nums2,(n>>1)+1);        }else{//为偶数return (findKthElm(nums1,nums2,n>>1)+findKthElm(nums1,nums2,(n>>1)+1))/2.0;        }    }};

 

照例贴上巨佬代码:

class Solution {public:double findMedianSortedArrays(vector& nums1, vector& nums2) {int len1=nums1.size();int len2=nums2.size();int k1=(len1+len2+1)/2;int k2=(len1+len2+2)/2;return (findK(nums1,nums2,0,len1-1,0,len2-1,k1)+findK(nums1,nums2,0,len1-1,0,len2-1,k2))/2;    }double findK(vector& nums1, vector& nums2,int left1,int right1,int left2,int right2,int k){int len1=right1-left1+1;int len2=right2-left2+1;if(len1>len2) return findK(nums2,nums1,left2,right2,left1,right1,k);if(len1==0) return nums2[left2+k-1];if(k==1) return min(nums1[left1],nums2[left2]);int pos1=left1+min(len1,k/2)-1;int pos2=left2+min(len2,k/2)-1;if(nums1[pos1]>nums2[pos2])      {return findK(nums1,nums2,left1,right1,pos2+1,right2,k-(pos2-left2+1));      }else      {return findK(nums1,nums2,pos1+1,right1,left2,right2,k-(pos1-left1+1));      }    }};

 

你可能感兴趣的:(leetcode)