一、问题描述
Description: 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)).
有两个有序的数组 nums1 和 nums2,大小分别为
二、解题报告
解法一:暴力法
题目要求里写了要求时间复杂度为
所谓暴力法,就是直接合并两个有序数组,然后返回合并后的数组的中位数。
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
vector<int> nums;
int M = nums1.size();
int N = nums2.size();
int i=0, j=0;
while(i<M && j<N)
{
if(nums1[i] < nums2[j])
nums.push_back(nums1[i++]);
else
nums.push_back(nums2[j++]);
}
while(i<M)
nums.push_back(nums1[i++]);
while(j<N)
nums.push_back(nums2[j++]);
if((M+N)%2 == 0) // 偶数
return (nums[(M+N)/2]+nums[(M+N)/2-1])/2.0;
else
return nums[(M+N)/2];
}
解法二:分治法
采用分治法的思想是求两个有序数组的第
假设数组A和B的元素个数都大于
当
A[k2−1]<B[k2−1] ,这表示A[0] ~A[k2−1] 的元素都在A和B合并之后的前k小的元素中。换句话说,我们要在剩下的元素里找k−k2 小的元素。当
A[k2−1]>B[k2−1] 时存在类似的结论。当
A[k2−1]=B[k2−1] 时,我们已经找到了第k 小的数,就是这个相等的元素。
通过上面的分析,我们可以采用递归的方式实现寻找第k小的数。另外需要考虑几个边界条件:
- 如果 A 或者 B 为空,则直接返回
B[k−1] 或者A[k−1] - 如果
k 为1,我们只需要返回A[0]和B[0]中的较小值 - 如果
A[k2−1]=B[k2−1] ,返回其中一个
函数实现如下:
int findKth(int A[], int m, int B[], int n, int k)
{
if (m > n) // 保证数组A的大小总是小于数组B的大小
return findKth(B, n, A, m, k);
if (m == 0) // 如果A为空
return B[k - 1];
if (k == 1) // 如果k为1
return min(A[0], B[0]);
// 每次把k分两半
int pa = min(k/2, m); /*A的元素可能小于k/2个*/
int pb = k - pa;
if (A[pa-1] < B[pb-1])
return findKth(A+pa, m-pa, B, n, k-pa);
else if (A[pa-1] > B[pb-1])
return findKth(A, m, B+pb, n-pb, k-pb);
else
return A[pa-1];
}
下面是 Solution:
class Solution {
public:
int findKth(int A[], int m, int B[], int n, int k)
{
if (m > n) // 保证数组A的大小总是小于数组B的大小
return findKth(B, n, A, m, k);
if (m == 0) // 如果A为空
return B[k - 1];
if (k == 1) // 如果k为1
return min(A[0], B[0]);
// 每次把k分两半
int pa = min(k/2, m); /*A的元素可能小于k/2个*/
int pb = k - pa;
if (A[pa-1] < B[pb-1])
return findKth(A+pa, m-pa, B, n, k-pa);
else if (A[pa-1] > B[pb-1])
return findKth(A, m, B+pb, n-pb, k-pb);
else
return A[pa-1];
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int *A = nums1.data();
int *B = nums2.data();
int m = nums1.size();
int n = nums2.size();
int total = m+n;
if (total%2 == 1) // 奇数个
return findKth(A, m, B, n, total/2+1);
else
return (findKth(A, m, B, n, total/2)
+ findKth(A, m, B, n, total/2+1)) / 2.0;
}
};
LeetCode答案源代码:https://github.com/SongLee24/LeetCode