4. Median of Two Sorted Arrays
介绍
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
题意:这个题目的内容还是很清楚的,就是有两个各自有序的数组,求两个数组合并成一个数组之后的中间值(如果合并后的数组大小是偶数,就求出来数组中间两个数的平均值)
解答
对于这道题,实际上就是求两个数组合并一个数组之后的第k个元素的值。
所以如果我们将两个元素直接合并乘一个数组,那么直接求取数组中下标为k-1的元素值,就是给定的结果。但是这种方法为O(m+n)。
当然,为进一步提高效率,我们可以考虑在merge的时候,并不是先生成新的数组,而是直接用两个指针分别指向两个数组的首部。并不断的推进两个指针,然后直到到达第k个元素上。
但是这种解法仍然为O(m+n)的时间复杂度。
这里记录了一种利用Binary Search
的算法来确定第k个元素的值。
下面就是介绍下这种解法:
我们假设对于两个数组nums1和nums2的数组长度都大于k/2,所以我们可以获得nums1[k/2-1]和nums2[k/2-1]的数据值。注意下标为k/2-1的元素实际上是数组的第k/2个元素。
对这两个数据进行比较,我们可以得到有且只有如下三种情况:
nums1[k/2-1] < nums2[k/2-1]
在这种情况下,我们能够保证nums1[0]到nums2[k/2-1]之间的所有元素都是第k个元素之前的数值。因为对于nums1[k/2-1]而言,比它小的元素应该最多只有k/2-1 + k/2 -1 = k-2个。所以num1[k/2-1]至多是第k-1个元素。
所以我们可以直接排除nums1[0]到nums1[k/2-1]之间的元素。
nums1[k/2] > nums2[k/2]
和情况1类似。nums1[k/2] == nums2[k/2]
那么我们可以肯定num1[k/2]就是k个元素的值。
事实上,我们很多时候无法保证k能够刚好均分为两份,事实上这个时候,我们只要保证第一个数组的第i的元素和第二个数组的第j个元素相加之和为i+j=k,即可。具体原因可以自己思索一下。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
//求两个有序数组总的第k个数
int m = nums1.size(), n = nums2.size();
int k = (m+n)/2;
if((m+n) & 0x01)
return getTheKNumber(nums1,0,m,nums2,0,n,k+1);
else
return ((double)getTheKNumber(nums1,0,m,nums2,0,n,k) + getTheKNumber(nums1,0,m,nums2,0,n,k+1))/2;
}
private:
int getTheKNumber(vector<int>& nums1,int ba,int ea,vector<int>& nums2,int bb,int eb,int k)
{
//保证nums1的查找长度始终小于等于nums2的查找长度。
if( (ea-ba) > (eb-bb) )
return getTheKNumber(nums2, bb, eb,nums1, ba, ea, k);
if(ba == ea) return nums2[k-1];
if(k == 1) return min(nums1[ba],nums2[bb]);
int pNums1 = min(ea-ba,k/2);
int pNums2 = k - pNums1;
if(nums1[ba+pNums1-1] < nums2[bb+pNums2-1])
return getTheKNumber( nums1, ba+pNums1, ea, nums2, bb, eb, k-pNums1);
else if(nums1[ba+pNums1-1] > nums2[bb+pNums2-1])
return getTheKNumber( nums1, ba, ea, nums2, bb+pNums2, eb, k-pNums2);
else
return nums1[ba+pNums1-1];
}
};