题目
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?
思路
题目有多种解法,难点在于用O(log (m+n))的方法去解决。
方法一:暴力法
直接将两个数组归并,合成一个新数组,再按题目的意思求中位数。奇数个数就找m+n/2+1,偶数个数找 m+n/2,m+n/2+1。复杂度O(m+n)
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m=nums1.length;
int n=nums2.length;
int x= (m+n)/2;
int[] result=new int[m+n];
double mid=0.0;
int p1=0;
int p2=0;
int p=0;
while(p1<m&&p2<n)
{
result[p++]=nums1[p1]<nums2[p2]?nums1[p1++]:nums2[p2++];
}
if(p1<m)
{
System.arraycopy(nums1,p1,result,p,m-p1);
}
if(p2<n)
{
System.arraycopy(nums2,p2,result,p,n-p2);
}
if((m+n)%2==0)
mid=(double) (result[x]+result[x-1])/2;
else
mid=result[x];
return mid;
}
}
方法二:双指针
直接找中位数,不需要归并,利用两个指针,将两个数组遍历,到达中位数位置就停下。复杂度O(m+n)
方法三:找第k小数
找中位数其实可以转换成找第k小数,k就是m+n/2+1。只要掌握求第K小数就行。
具体解法:同样以1~17为例
1.求k,(1+17)/2=9
2.折半, k / 2 = 4
3.将折半的两组数的最大值进行比较,4和12,删掉小的那组,1234删掉。
4.删掉之后重新上述过程,还剩9-4=5 现在变成找第5小的数,5/2=2
5.比较6和10,删掉56
6.一直重复直到不能删。
关于为什么比较两组数中最大的数,删掉小的那组就行的原因。
换句话说怎么证明4一定不是第k小的。
假设4是第k个数左边的,只需证明第k个数右边的位置,在1234是左边的情况下是能够填满的。
方法四:官方给出的划分数组
也是利用二分查找,但看不太明白。。。