题目
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
分析
如果第一个字符串长度是len1,第二个字符串长度是len2,两个数组合并之后个数可能是奇数也可能是偶数,求中位数需要下图公式进行统一,我们需要找第(len1+len2+1)/2大的数和第(len1+len2+2)/2大的数然后再除以2就大功告成。
如何找第(len1+len2+1)/2大的数和第(len1+len2+2)/2大的数?就当作是找第k大的数
我们在两个数组中各取k/2个数的数组,然后比较两个数组k/2-1的下标对应的值,由于两个数组都是正序,去掉比较小的值前面的数(包括小的值)
k = 5
k = 5-2=3
k = 3-1=2
k = 2-1=1
发现其实可以通过调整下标的递归的方式来找到第k大的数,具体详细见代码。
代码
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
return (getK(nums1,nums2,0,m-1,0,n-1,(m+n+1)/2)+getK(nums1,nums2,0,m-1,0,n-1,(m+n+2)/2))*0.5;
}
int getK(int[] nums1,int[] nums2,int l1,int r1,int l2,int r2,int k){
int len1 = r1-l1+1;
int len2 = r2-l2+1;
if(len1>len2){
return getK(nums2,nums1,l2,r2,l1,r1,k);
}
if(len1 ==0){
return nums2[l2+k-1];
}
if(k==1){
return Math.min(nums1[l1],nums2[l2]);
}
int idx1 = l1+Math.min(len1,(k/2))-1;
int idx2 = l2+Math.min(len2,(k/2))-1;
if(nums1[idx1]>nums2[idx2]) return getK(nums1,nums2,l1,r1,idx2+1,r2,k-(idx2-l2+1));
return getK(nums1,nums2,idx1+1,r1,l2,r2,k-(idx1-l1+1));
}
}