leetcode地址:寻找两个正序数组的中位数
描述:
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
提示:
nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
int left = (m+n+1)/2;
int right = (m+n+2)/2;
return (findKthElement(nums1,0,nums2,0,left)+findKthElement(nums1,0,nums2,0,right))/2.0;
}
public int findKthElement(int[] nums1,int i,int[] nums2 ,int j,int k){
if(i>=nums1.length) return nums2[j+k-1];
if(j>=nums2.length) return nums1[i+k-1];
if(k==1) return Math.min(nums1[i],nums2[j]);
int midVal1 = i+k/2-1<nums1.length?nums1[i+k/2-1]:Integer.MAX_VALUE;
int midVal2 = j+k/2-1<nums2.length?nums2[j+k/2-1]:Integer.MAX_VALUE;
if(midVal1<midVal2){
return findKthElement(nums1,i+k/2,nums2,j,k-k/2);
}else{
return findKthElement(nums1,i,nums2,j+k/2,k-k/2);
}
}
题解:
如果采用将两个数组合并,并且有序后进行寻找的方式,显然是比较简单的,但是此时时间复杂度比较大,不符合题目给出时间复杂度log(m+n),由于log(m+n),那么就要想到使用二分法的方式进行解决。
两个有序的数组中找到中位数,如果两个数组的长度和为奇数或者为偶数,即表示找到找中位数为两个数之和,取均值。
该题目就演变为找到第k大的数值问题
存在三种情况:
①i大于等于第一个数组的长度,那么就意味着直接在第二个数组中找
②j大于等于第二个数组的长度,那么就意味着直接在第一个数组中找
③当k==1时,那么就得到当前两个数组下标比较小的数值
如果为正常的返回情况,那么得到数值,并且比较二者数值的大小,并且将小的部分在数组中去掉。