题目描述:
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。
请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例:
nums1 = [1, 3] nums2 = [2] 则中位数是 2.0
nums1 = [1, 2] nums2 = [3, 4] 则中位数是 (2 + 3)/2 = 2.5
代码:
class Solution {
public:
double findMedianSortedArrays(vector& nums1, vector& nums2) {
int l1 = nums1.size();
int l2 = nums2.size();
int l = l1 + l2;
int i = 0, j = 0;
int median = l / 2;
int cnt = 0;
int now = 0;
int left, right;
while(i < l1 || j < l2){
if(cnt == median){
left = now;
}
else if(cnt == median+1){
right = now;
break;
}
if(i == l1)
now = nums2[j++];
else if(j == l2)
now = nums1[i++];
else if(nums1[i]nums2[j])
now = nums2[j++];
cnt++;
}
if(l%2)
return (double)right;
else return (double)(left + right)/2;
}
};
归并排序的思路,本来用了一个数组保存排序结果,后来看了一篇题解反应过来并不需要,两个数组长度已知中位的位置就是固定的,只要找到那个位置的数即可。
虽然通过了,其实并未达到要求的时间复杂度,看官方题解,要想达到log的时间复杂度,二分是个正确的选择。
二分思路:
由于数组长度已知,求中位数可化解为求第k小的数,每次去掉k/2个数。
class Solution {
public:
double findMedianSortedArrays(vector& nums1, vector& nums2) {
int l1 = nums1.size();
int l2 = nums2.size();
int k1 = (l1 + l2 + 1)/2;
int k2 = (l1 + l2 + 2)/2;
return (get_kth(nums1, 0, l1-1, nums2, 0, l2-1, k1) + get_kth(nums1, 0, l1-1, nums2, 0, l2-1, k2)) /2;
}
double get_kth(vector& nums1, int begin1, int end1, vector& nums2, int begin2, int end2, int k){
int l1 = end1 - begin1 + 1;
int l2 = end2 - begin2 + 1;
if(l1 > l2)//确保如果有数组空了一定是第一个
return get_kth(nums2, begin2, end2, nums1, begin1, end1, k);
//两种情况,如果其中一个数组空了,直接返回另一数组的第k个值
//如果k=1,比较两个数组的头值并返回较小的那个
if(l1 == 0) return nums2[begin2+k-1];
if(k == 1) return min(nums1[begin1], nums2[begin2]);
int i = min(end1, begin1+k/2-1);
int j = min(end2, begin2+k/2-1);
int n1 = nums1[i];
int n2 = nums2[j];
if(n1 < n2)
return get_kth(nums1, i+1, end1, nums2, begin2, end2, k-i+begin1-1);
else return get_kth(nums1, begin1, end1, nums2, j+1, end2, k-j+begin2-1);
}
};