1.Median of Two Sorted Array
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:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
Difficulty:Hard
Explanation:
1.这道题目相对于其他题目来说是比较难的,虽然一般来说要找到两个数组中的中位数的话,只要将两个数组合在一起再找中位数就行了,但是这样做的时间复杂度是不满足O(log(m+n))的。因此,利用这种平常的方法是不能解决这道题目的。
2.对于这道题目主要是使用LeetCode解释中所提到的迭代方法。这种方法的目的是在于直接寻找两个数组之间的中位数而不经过两个数组的结合和排序,而是根据中位数的特殊性质来进行寻找。一般来说,只要满足以下这个条件的数就可以说是数组的中位数了:
(1)将已排序的数组分为大小相等的两部分,且前一部分的数都比后一部分中的数要小,则这个数就是这个数组的中位数。
而对于两个数组的中位数,其实也是只要找到满足以下条件的数就可说是这两个数组的中位数了:
(1)将两个数组中的所有元素分成大小两部分,且前一部分的数都比后一部分中的数要小,则这个数就是这两个数组的中位数了。
即length(RightPart)==length(LeftPart)&&Max(RightPart)<=Min(LeftPart)
在数组A或者B中找到满足这个条件的元素即为两个数组的中位数
3.如何在A或者B中找到这个中位数呢?设A[i],B[j]为数组A位于后一部分的最小的元素和数组B位于后一部分的最小的元素,而这两个元素当满足以下两个条件的时候就可以找到这两个数组的中位数了。
(1)j=(m+n+1)/2-i,(m为数组A的大小,n为数组B的大小)
(2)B[j]>A[i-1]&&A[i]>B[j-1]
我们可以利用二分法去找到满足条件的i,假设i是区间[imin,imax]中的一个值。如果求得B[j]<=A[i-1],证明i过大,那么下一个循环应该在[imin,i-1]之间查找新的i;相反则应该在[i+1,imax]之间寻找更大的i,直到找到满足条件的i为止。找到这个i也意味着找到了中位数
code
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
if(nums1.size()>nums2.size())
{
return core(nums2,nums1);
}
else
{
return core(nums1,nums2);
}
}
double core(vector<int>& nums1, vector<int>& nums2) {
int imin, imax;
int m,n;
m = nums1.size();
n = nums2.size();
imin = 0;
imax = m;
if (m == 0)
{
return n % 2 == 0 ? (double)(nums2[n / 2] + nums2[n / 2 - 1]) / 2 : nums2[n / 2];
}
if (n == 0)
{
return m % 2 == 0 ?(double) (nums1[m / 2] + nums1[m / 2 - 1]) / 2 : nums1[m / 2];
}
while (1)
{
int i = (imin + imax) / 2;
int j = (m + n + 1) / 2 - i;
if ((j == 0 || i == m || nums1[i] >= nums2[j - 1]) && (j == n || i == 0 || nums1[i - 1] <= nums2[j]))
{
int maxLeft = 0;
if (i == 0)
{
maxLeft = nums2[j - 1];
}
else if (j == 0)
{
maxLeft = nums1[i - 1];
}
else
{
maxLeft = nums1[i - 1] > nums2[j - 1] ? nums1[i - 1] : nums2[j - 1];
}
if ((m + n) % 2 == 1)
{
return maxLeft;
}
int minRight = 0;
if (i == m)
{
minRight = nums2[j];
}
else if (j == n)
{
minRight = nums1[i];
}
else
{
minRight = nums1[i] < nums2[j] ? nums1[i] : nums2[j];
}
return (double)(maxLeft + minRight) / 2;
}
else if (i<imax&&nums2[j - 1] > nums1[i])
{
imin = i + 1;
}
else if (i>imin&&nums1[i - 1] > nums2[j])
{
imax = i - 1;
}
}
return 0;
}
};