题目
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
示例:
思路
根据中位数的定义,当 m+n 是奇数时,中位数是两个有序数组中的第 (m+n)/2 个元素,当 m+n 是偶数时,中位数是两个有序数组中的第 (m+n)/2个元素和第 (m+n)/2+1 个元素的平均值。因此,这道题可以转化成寻找两个有序数组中的第 k 小的数,其中 k 为 (m+n)/2或 (m+n)/2+1。
代码
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
int totalLen = len1 + len2;
//奇数,中位数是两个有序数组中的第 (m+n)/2 个元素
if(totalLen % 2 == 1){
double median = getKthElement(nums1,nums2,totalLen/2+1);
return median;
}else{
//偶数时,中位数是两个有序数组中的第 (m+n)/2个元素和第 (m+n)/2+1 个元素的平均值
double median = (getKthElement(nums1,nums2,totalLen/2) + getKthElement(nums1,nums2,totalLen/2 + 1)) / 2.0;
return median;
}
}
public int getKthElement(int[] nums1,int[] nums2,int k){
int len1 = nums1.length;
int len2 = nums2.length;
int index1 = 0, index2 = 0;
while(true){
if(index1 == len1){
return nums2[index2+k-1];
}
if(index2 == len2){
return nums1[index1+k-1];
}
//我们要找第 1 小的数字,所以只需判断两个数组中第一个数字哪个小就可以了
if(k==1){
return Math.min(nums1[index1],nums2[index2]);
}
int half = k / 2;
//删除" 了一些元素(这些元素都比第 k 小的元素要小)更新index的值
//如果超过数组的长度,就指向数组的末尾
int newIndex1 = Math.min(index1 + half,len1) - 1;
int newIndex2 = Math.min(index2 + half,len2) - 1;
if(nums1[newIndex1] <= nums2[newIndex2]){
k -= (newIndex1-index1+1);
index1 = newIndex1 + 1;
}else{
k -= (newIndex2-index2+1);
index2 = newIndex2 + 1;
}
}
}
}