题目
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 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
解析:
这道题看着貌似简单,实际上没有那么简单~
首先上我自己写的超级笨拙的代码(JAVA,当然还可以优化~):
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len=nums1.length+nums2.length;
if(len==0){
return 0;
}
if(nums1.length<nums2.length){
return findMedianSortedArrays(nums2,nums1);
}
boolean even=false;
int middle;
if (len%2==0){
even=true;
middle=len/2;
}else{
middle=(len+1)/2;
}
if(nums2.length==0){
if(even)
return ((double)nums1[middle-1]+(double)nums1[middle])/2;
else
return (double)nums1[middle-1];
}
int temp=0;
int middleValue=0;
int i=0;
int j=0;
for (;i<nums1.length+1;){
if(j==nums2.length&&i==nums1.length){
break;
}
if(j==nums2.length){
temp++;
i++;
if(temp==middle&&!even)
return (double)nums1[i-1];
if(temp==middle&&even)
middleValue=nums1[i-1];
if(temp==(middle+1)&&even)
return ((double)middleValue+(double)nums1[i-1])/2;
continue;
}
for(;j<nums2.length;){
if(nums1.length==i){
temp++;
j++;
if(temp==middle&&!even)
return (double)nums2[j-1];
if(temp==middle&&even)
middleValue=nums2[j-1];
if(temp==middle+1&&even)
return ((double)middleValue+(double)nums2[j-1])/2;
continue;
}
if(nums1[i]<nums2[j]){
temp++;
i++;
if(temp==middle&&!even)
return (double)nums1[i-1];
if(temp==middle&&even)
middleValue=nums1[i-1];
if(temp==(middle+1)&&even)
return ((double)middleValue+(double)nums1[i-1])/2;
break;
}else if (nums1[i]>nums2[j]){
temp++;
j++;
if(temp==middle&&!even)
return (double)nums2[j-1];
if(temp==middle&&even)
middleValue=nums2[j-1];
if(temp==(middle+1)&&even)
return ((double)middleValue+(double)nums2[j-1])/2;
}else{
i++;
j++;
temp=temp+2;
if((temp==middle||temp-1==middle)&&!even)
return (double)nums2[i-1];
if((temp==middle||temp-1==middle)&&even)
middleValue=nums1[i-1];
if((temp==(middle+1)||temp-1==middle+1)&&even)
return ((double)middleValue+(double)nums2[i-1])/2;
break;
}
}
}
return 0;
}
以上代码实际上就是一个排序~,因为给的数组是有序的,因此当它排到中位数的时候就返回了,此时若m+n为偶数时,它执行m+n/2次,奇数同理。所以时间复杂度为O(n)。不符合要求~~但是leetcode木有提示,仔细看题目,时间复杂度要求O(log(m+n)).
然后,去网上搜了一下牛人的解答:leetcode之 median of two sorted arrays
里面证明也写的很详细,好汗颜~,具体用go语言实现了一下,因为java代码有点不方便。leetcode accept了
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
m:= len(nums1)
n:=len(nums2)
total := m+n;
if total%2==1 {
return findKth(nums1, m, nums2, n, total / 2 + 1)
} else {
return (findKth(nums1, m, nums2, n, total / 2)+ findKth(nums1, m, nums2, n, total / 2 + 1)) / 2
}
}
func findKth(nums1 []int,size1 int, nums2 []int,size2 int ,k int) float64{
if size1>size2{
return findKth(nums2,size2,nums1,size1,k)
}
if size1==0{
return float64(nums2[k-1])
}
if k==1{
if nums1[0]>nums2[0]{
return float64(nums2[0])
}
return float64(nums1[0])
}
pa:=k/2
if pa>size1{
pa=size1
}
pb:=k-pa
if nums1[pa-1]>nums2[pb-1]{
return findKth(nums1,size1,nums2[pb:size2],size2-pb,k-pb)
}else if nums1[pa-1]<nums2[pb-1]{
return findKth(nums1[pa:size1],size1-pa,nums2,size2,k-pa)
}else{
return float64(nums1[pa-1])
}
}
一看到时间复杂度为log**那么第一应该想到的就是二分搜索。此算法,算是二分删除。
一开始觉得此算法会漏掉一些情况,比如1,3,4,5和2,3,4,5,6这个情况此时k/2是2(舍掉小数位后面的),那么此时3=3,而3并不是中位数。实际上两个数组比较的索引是这样算的:
pa:=k/2 if pa>size1{ pa=size1 } pb:=k-pa
这样保证了相等时就是中位数,因为pa+pb=k。当然前提数组是升序排列。