题目描述
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
题解
最简单的办法就是合并数组,再取中位数。但是时间复杂度为O(m+n) > O(log (m+n)),不符合要求。
略加思索,中位数与位置相关。在一个总长m + n的数组里中位数的位置为(m+n-1)/2。如果我们把长度为n的数组作为参考,中位数位置为(n-1)/2位置,当我们把长度为m的数组合进去的时候,中位数的位置就会依据长度为m的数组合进去的元素位置做出移动。
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
// 保证nums1是两个数组中比较元素较少的那个
if(nums1.length > nums2.length){
int[] temp = nums1;
nums1 = nums2;
nums2 = temp;
}
int min = 0;
int max = nums1.length;
int half = (nums1.length + nums2.length + 1)/2;
while(min <= max){
int i = (min + max)/2;
int j = half - i;
if(i < max && nums1[i] < nums2[j-1]){
min = i + 1;
}else if(i > min && nums1[i-1] > nums2[j]){
max = i - 1;
}else{
// 中位数将数组一分为二
//左半部分最大的值
int maxLeft;
if(i == 0){
maxLeft = nums2[j-1];
}else if(j == 0){
maxLeft = nums1[i-1];
}else{
maxLeft = Math.max(nums1[i-1],nums2[j-1]);
}
if ( (nums1.length + nums2.length) % 2 == 1 ) {
return maxLeft;
}
//右半部分最小的值
int minRight;
if( i == nums1.length){
minRight = nums2[j];
}else if(j == nums2.length){
minRight = nums1[i];
}else{
minRight = Math.min(nums1[i],nums2[j]);
}
return (maxLeft + minRight) / 2.0;
}
}
return 0.0;
}
复杂度分析:
- 时间复杂度:O(log(min(m,n)),m和n为两个数组的长度;
- 空间复杂度:O(1)。
题目地址:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/