题目来源:https://leetcode.com/problems/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)).
题目要求:两个排序数组中,计算出他们的中位数。中位数的概念:数列中的个数是奇数时,中位数是中间数,否则,是中间两个数的平均数。
刚开始把O(log(m+n))错误的以为是O(m+n),所以想到的就是归并排序的思路,讲所有数据进行排序,然后可以取得中位数。最后,去LeetCode测试Accept了,谁知道等我开写博客的时候,才发现时间复杂度要求为O(log(m+n))。废话不说,先把O(m+n)的代码贴上来。
class Solution {
public:
int getOneStoredArray(vector<int> &nums1, vector<int > &nums2, int &p1, int&p2)
{
if (p1 < nums1.size() && p2 < nums2.size())
{
int x = nums1[p1];
int y = nums2[p2];
if (x < y)
{
p1++;
return x;
}
else
{
p2++;
return y;
}
}
if (p1 < nums1.size())
{
p1++;
return nums1[p1 - 1];
}
else
{
p2++;
return nums2[p2 - 1];
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
if (nums1.size() == 0 && nums2.size() == 0)
return 0;
int nums1_pointer = 0, nums2_pointer = 0;
int size = nums1.size() + nums2.size();
if (size % 2 == 0)
{
int cnt = size / 2;
for (int i = 0; i < cnt-1; i++)
{
getOneStoredArray(nums1, nums2, nums1_pointer, nums2_pointer);
}
int x = getOneStoredArray(nums1, nums2, nums1_pointer, nums2_pointer);
int y = getOneStoredArray(nums1, nums2, nums1_pointer, nums2_pointer);
return (x + y) / 2.0;
}
else
{
int cnt = size / 2 + 1;
for (int i = 0; i < cnt-1; i++)
{
getOneStoredArray(nums1, nums2, nums1_pointer, nums2_pointer);
}
return getOneStoredArray(nums1, nums2, nums1_pointer, nums2_pointer);
}
}
};
那么如果想要复杂度要求是O(log(m+n)),第一感觉就是寻找log(N)的算法,二分查找的复杂度是log(N)。想到的第一种思路是,求出两个列表的中位数x和y,然后将两个数组中同时小于x和y的一部分删除,然后再使用第k小值的算法。但是最终没有具体算法。
第二种思路:中位数实际上就是第(m+n)/2的数,所以直接使用第k小值的算法。
具体思路在于,将两个数组每次拿去k/2的元素个数,然后求接下来求第k-k/2小值元素。
方法:首先求出数组x=nums1[k/2] y=nums2[k/2]。然后比较x和y的数值,如果x小,则直接移走nums1的前k/2个元素,然后求第k-k/2小值元素,否则,移走nums2的前k/2个元素,然后求第k-k/2小值元素(当然实际情况下,还需要考虑num1和nums2的长度是否大于k/2)。
期中还有三个基本情况:
1. nums1的长度为0,直接返回nums2的第k个元素即可。
2. mums2的长度为0,直接返回nums1的第k个元素。
3. 如果k==1,直接返回nums1[0]和nums2[0]的最小值。
代码如下:
class Solution {
public:
int getOneStoredArray(vector<int> &nums1, vector<int > &nums2, int nums1begin,int nums1end,int nums2begin,int nums2end,int kth)
{
if (nums1begin >= nums1end)
return nums2[nums2begin + kth - 1];
if (nums2begin >= nums2end)
{
return nums1[nums1begin + kth - 1];
}
if (kth == 1)
{
int x = nums1[nums1begin];
int y = nums2[nums2begin];
return x<y?x:y;
}
int index1 = nums1begin + kth / 2 - 1;
int index2 = nums2begin + kth / 2 - 1;
if (index1 >= nums1end)
index1 = nums1end-1;
if (index2>=nums2end)
index2 = nums2end - 1;
if (nums1[index1] < nums2[index2])
{
return getOneStoredArray(nums1, nums2, index1 + 1, nums1end, nums2begin, nums2end, kth - index1 + nums1begin - 1);
}
else
{
return getOneStoredArray(nums1, nums2, nums1begin, nums1end, index2+1, nums2end, kth - index2 + nums2begin - 1);
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
if (m + n == 0)
return 0;
if ((m + n) & 1 == 1)
{
return getOneStoredArray(nums1, nums2, 0, nums1.size(), 0, nums2.size(), (m + n) / 2 + 1);
}
else
{
int x = getOneStoredArray(nums1, nums2, 0, nums1.size(), 0, nums2.size(), (m + n) / 2 + 1);
int y=getOneStoredArray(nums1, nums2, 0, nums1.size(), 0, nums2.size(), (m + n) / 2 );
return (x + y) / 2.0;
}
}
};