题目
给定两个大小分别为 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
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
合并数组
- 解题思路
不考虑时间复杂度的话,最简单的就是合并数组,找一下数组中间位置的数。
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
int[] nums3 = new int[nums1.length+nums2.length];
int len = nums3.length;
int end = len/2;
int idx1=0;
int idx2=0;
int idx3=0;
while (idx3<=end)
{
if(idx2>nums2.length-1)
{
nums3[idx3]=nums1[idx1];
idx3++;
idx1++;
continue;
}
if(idx1>nums1.length-1)
{
nums3[idx3]=nums2[idx2];
idx2++;
idx3++;
continue;
}
if(nums1[idx1]>=nums2[idx2])
{
nums3[idx3]=nums2[idx2];
idx2++;
}
else
{
nums3[idx3]=nums1[idx1];
idx1++;
}
idx3++;
}
if(len%2==0)
{
return (double)(nums3[end]+nums3[end-1])/2;
}
return (double)nums3[end];
}
二分法
- 解题思路
由于题目限制时间复杂组,log(m+n),那么就需要考虑使用二分法。
在两个数组中,我们可以找到这样一条线,分割两个数组,同时满足两个条件- 分割线左侧的数量等于右侧的数量
- 分割线左侧的最大数,小于右侧的最小数
public static double findMedianSortedArrays2(int[] nums1, int[] nums2) {
//为了方便保证,第一个数组小于第二个数组
if(nums1.length>nums2.length)
{
int[] temp = nums1;
nums1=nums2;
nums2=temp;
}
int len1= nums1.length;
int len2 = nums2.length;
//这个满足奇偶两种情况
int totalLeft = (len1+len2+1)/2;
//在区间(0,m]找分割线
//使得nums1[i-1]<=nums2[j] && nums[j-1]<=num[i]
int left=0;
int right=len1;
//需要找到一条恰当的分割线,分割线,分割两个数组,左面的数要小于右面的数(两个数组是有序的)。
//这个分割线左侧的元素等于totalLeft = (len1+len2+1)/2;
while(left<right)
{
// i 为nums1的index,每次2分递增
// j 为nums2的index,等于totalLeft-i
// i 为分割线在数组1右面那个位置
int i = left+(right-left+1)/2;
// j 为分割线在数组2右面那个位置
int j = totalLeft-i;
// 分割线,左边数值,大于分割线右边的数值
// nums1[i-1]<=nums2[j]
if(nums1[i-1]>nums2[j])
{
//不符合条件时
//下一轮搜索区间[left,i-1]
right=i-1;
}else
{
//下一轮搜索区间[i,right]
left=i;
}
}
int i = left+(right-left+1)/2;
int j = totalLeft-i;
int nums1LeftMax = i==0?Integer.MIN_VALUE:nums1[i-1];
int nums1RightMin = i==len1?Integer.MAX_VALUE:nums1[i];
int nums2LeftMax = j==0?Integer.MIN_VALUE:nums2[j-1];
int nums2RightMin = j==len2?Integer.MAX_VALUE:nums2[j];
if((len1+len2)%2==1)
{
return (double)Math.max(nums1LeftMax,nums2LeftMax);
}else
{
return (double)(Math.max(nums1LeftMax,nums2LeftMax)+Math.min(nums1RightMin,nums2RightMin))/2;
}
}
标签:正序,int,中位数,length,数组,nums1,nums2,nums3
From: https://www.cnblogs.com/huacha/p/16863157.html