问题描述:
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)).
分析:这道题非常难,单纯解这道题可以有好几种方法:
1、两个索引分别对两个数组进行遍历,当计数到k时,跳出。返回对应值。
2、组织一个最大堆,堆的容量为k,当两个数组中对应值都大于堆顶元素时,退出,返回堆顶元素。
代码如下:24ms
int findKthNums(int *nums1,int nums1Size,int *nums2,int nums2Size,int k){
int index1 = 0,index2 = 0;
int count = 0;
int res = 0;
while(index1<nums1Size && index2<nums2Size && count<k){
if(nums1[index1]<nums2[index2]){
res = nums1[index1++];
}else{
res = nums2[index2++];
}
count++;
}
while(index1<nums1Size && count<k){
res = nums1[index1++];
count++;
}
while(index2<nums2Size && count<k){
res = nums2[index2++];
count++;
}
return res;
}
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
int sum = nums1Size+nums2Size;
int mid = sum/2;
if(sum%2)
return findKthNums(nums1,nums1Size,nums2,nums2Size,mid+1);
else
return (findKthNums(nums1,nums1Size,nums2,nums2Size,mid)+findKthNums(nums1,nums1Size,nums2,nums2Size,mid+1))/2.0;
}
但是上述代码并不符合题目要求,上述时间复杂度为O(n+m),而要求为O(log(m+n))。一般而言求log数都是采用类似于2分的方法。
那咋二分,二分啥?这个就是问题所在了。
二分两个数组,那得出的东西啥都不是。所以,可以二分k,因为k = (m+n)/2,所以时间复杂度为O(log(m+n)/2) = O(log(m+n)),满足条件。
出于简单起见(代码中并未严格这样,因为k有偶数和奇数之分)。
我们比较num1[k/2-1]和num2[k/2-1],为啥比较这两个数,因为num1[k/2-1]正好是第一个数组的第k/2个数,同理num2也是,那如果num1[k/2-1]
int findKthNums(int *nums1, int nums1Size, int *nums2, int nums2Size, int k) {
if (nums1Size < nums2Size)
return findKthNums(nums2, nums2Size, nums1, nums1Size, k);
if (nums2Size <= 0) {//num1Size>nums2Size,并由上条判断决定
return nums1[k - 1];
}
if (k == 1)
return nums1[0] < nums2[0] ? nums1[0] : nums2[0];
int index = k / 2>nums2Size ? nums2Size : k / 2;
if (nums1[k- index -1] < nums2[index - 1]) {
return findKthNums(nums1 + k-index, nums1Size - k+index, nums2, nums2Size, index);
}
else if (nums1[k-index - 1]>nums2[index - 1]) {
return findKthNums(nums1, nums1Size, nums2 +index, nums2Size - index, k-index);
}
else{
return nums1[index- 1];
}
}
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
int sum = nums1Size + nums2Size;
if (sum % 2)//奇数
return findKthNums(nums1, nums1Size, nums2, nums2Size, sum / 2 + 1);
else//偶数
return (findKthNums(nums1, nums1Size, nums2, nums2Size, sum / 2) +
findKthNums(nums1, nums1Size, nums2, nums2Size, sum / 2 + 1)) / 2.0;
}