题目
给定两个大小为 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
示例 3
输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000
示例 4
输入:nums1 = [], nums2 = [1]
输出:1.00000
示例 5
输入:nums1 = [2], nums2 = []
输出:2.00000
提示
- nums1.length == m
- nums2.length == n
- 0 <= m <= 1000
- 0 <= n <= 1000
- 1 <= m + n <= 2000
- -106 <= nums1[i], nums2[i] <= 106
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
解题思路
从复杂度为 O(log (m+n))可以想象的出此题应该是二分法的思想。在一个有序数组中,中位数仅受中间一个或是两个数字的影响,那么分成两个有序数组来看,我们仅需找到相应的四个数字来进行比较即可以得出相应结果。
java实现
这里留作思考,我认为我的思路也是遵循 O(log (min(m,n)))
个人版(二分法)
执行用时:3 ms, 在所有 Java 提交中击败了82.41%的用户
class Solution {
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
return findMedianSortedArrays(nums2, nums1);
}
int shorterArrayFlag = 0;
int longerArrayFlag = (nums1.length+nums2.length) / 2;
int path = (nums1.length + 1) / 2;
boolean evenFlag = (nums1.length+nums2.length) % 2 == 0 ? true : false;
int shorterFlagLeftValue,shorterFlagRightValue,longerFlagLeftValue,longerFlagRightValue;
while(true){
shorterFlagLeftValue = shorterArrayFlag <= 0 ? Integer.MIN_VALUE : nums1[shorterArrayFlag - 1];
shorterFlagRightValue = shorterArrayFlag >= nums1.length ? Integer.MAX_VALUE : nums1[shorterArrayFlag];
longerFlagLeftValue = longerArrayFlag <= 0 ? Integer.MIN_VALUE : nums2[longerArrayFlag - 1];
longerFlagRightValue = longerArrayFlag >= nums2.length ? Integer.MAX_VALUE : nums2[longerArrayFlag];
if (shorterFlagLeftValue <= longerFlagRightValue && longerFlagLeftValue <= shorterFlagRightValue) {
return evenFlag ? evenArrayResult(shorterFlagLeftValue, longerFlagLeftValue, shorterFlagRightValue, longerFlagRightValue) : oddArrayResult(shorterFlagRightValue, longerFlagRightValue);
} else if (shorterFlagLeftValue > longerFlagRightValue) {
shorterArrayFlag -= path;
longerArrayFlag += path;
path = (path + 1) / 2;
} else if (longerFlagLeftValue > shorterFlagRightValue) {
shorterArrayFlag += path;
longerArrayFlag -= path;
path = (path + 1) / 2;
}
}
}
public static double oddArrayResult(int shorterFlagRightValue, int longerFlagRightValue) {
return shorterFlagRightValue < longerFlagRightValue ? (double) shorterFlagRightValue : (double) longerFlagRightValue;
}
public static double evenArrayResult(int shorterFlagLeftValue, int longerFlagLeftValue, int shorterFlagRightValue, int longerFlagRightValue) {
int leftValue = shorterFlagLeftValue > longerFlagLeftValue ? shorterFlagLeftValue : longerFlagLeftValue;
int rightValue = shorterFlagRightValue < longerFlagRightValue ? shorterFlagRightValue : longerFlagRightValue;
return (double) (leftValue + rightValue) / 2;
}
}
官方
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
return findMedianSortedArrays(nums2, nums1);
}
int m = nums1.length;
int n = nums2.length;
int left = 0, right = m;
// median1:前一部分的最大值
// median2:后一部分的最小值
int median1 = 0, median2 = 0;
while (left <= right) {
// 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]
// 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]
int i = (left + right) / 2;
int j = (m + n + 1) / 2 - i;
// nums_im1, nums_i, nums_jm1, nums_j 分别表示 nums1[i-1], nums1[i], nums2[j-1], nums2[j]
int nums_im1 = (i == 0 ? Integer.MIN_VALUE : nums1[i - 1]);
int nums_i = (i == m ? Integer.MAX_VALUE : nums1[i]);
int nums_jm1 = (j == 0 ? Integer.MIN_VALUE : nums2[j - 1]);
int nums_j = (j == n ? Integer.MAX_VALUE : nums2[j]);
if (nums_im1 <= nums_j) {
median1 = Math.max(nums_im1, nums_jm1);
median2 = Math.min(nums_i, nums_j);
left = i + 1;
} else {
right = i - 1;
}
}
return (m + n) % 2 == 0 ? (median1 + median2) / 2.0 : median1;
}
}
优质答案
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m,n,i,j,k;
int max =1000000;
double ans, ansl;
ans = 0;
ansl = 0;
m = nums1.length;
n = nums2.length;
int mid = (m+n)/2;
if(m == 0)
{
if(n%2==1)
return (double)nums2[mid];
else
return ((double)nums2[mid]+(double)nums2[mid-1])/2;
}
else if(n == 0)
{
if(m%2==1)
return nums1[mid];
else
return ((double)nums1[mid]+(double)nums1[mid-1])/2;
}
else if((m+n)%2==1)
{
i=0;
j=0;
for(k=0;k<=mid;k++){
if(nums1[i]<nums2[j])
{
ans = nums1[i];
if(i<m-1)
i++;
else
nums1[i]=max;
}
else
{
ans = nums2[j];
if(j<n-1)
j++;
else
nums2[j]=max;
}
}
return ans;
}
else
{
i=0;
j=0;
for(k=0;k<=mid;k++){
if(nums1[i]<nums2[j])
{
ansl = ans;
ans = nums1[i];
if(i<m-1)
i++;
else
nums1[i]=max;
}
else
{
ansl = ans;
ans = nums2[j];
if(j<n-1)
j++;
else
nums2[j]=max;
}
}
return (ans+ansl)/2;
}
}
}