4. 寻找两个正序数组的中位数
难度困难3569
给定两个大小为 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
-10<sup>6</sup> <= nums1[i], nums2[i] <= 10<sup>6</sup>
My solution(归并法)
import java.util.Arrays;
public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int[] arr=new int[nums1.length+nums2.length];
for(int i=0;i<nums1.length;i++)
arr[i]=nums1[i];
for (int i =0;i<nums2.length;i++)
arr[i+nums1.length]=nums2[i];
Arrays.sort(arr);
return arr.length%2==1?arr[(arr.length-1)/2]:(arr[arr.length/2]+arr[arr.length/2-1])/2.0;
}
}
执行用时:5 ms, 在所有 Java 提交中击败了14.05%的用户
内存消耗:39.6 MB, 在所有 Java 提交中击败了81.65%的用户
关于Arrays的sort方法,这里有一篇文章详细介绍了它使用的算法https://www.cnblogs.com/baichunyu/p/11935995.html
我的解法肯定达不到题目要求的时间复杂度O(logn),一般出现这样的对数时间复杂度,都是用到了二分查找法:
二分查找
public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n=nums1.length+nums2.length;
if(n%2==1)//和为奇数,返回第n/2+1个数
return getMid(nums1,nums2,n/2+1);
if(n%2==0)//和为偶数,返回第n/2个数和第n/2+1个数的和的一半
return (getMid(nums1,nums2,n/2)+getMid(nums1,nums2,n/2+1))/2.0;
else
return 0;
}
public double getMid(int[] nums1, int[] nums2,int k){
//返回第k个数
int start1=0,start2=0;
while(true){
if(start1==nums1.length)
return nums2[start2+k-1];
if(start2==nums2.length)
return nums1[start1+k-1];
if(k==1)
return Math.min(nums1[start1],nums2[start2]);
int index1=Math.min(start1+k/2-1,nums1.length-1);
int index2=Math.min(start2+k/2-1,nums2.length-1);
if(nums1[index1]<=nums2[index2])
{
k-=index1-start1+1;
start1=index1+1;
}
else
{
k-=index2-start2+1;
start2=index2+1;
}
}
}
}
该代码是leetcode官方二分法解答的简化版,其主要就是定义了一个函数,运用二分法获取两个数组中从小到大第k个元素
其中start1,start2分别代表数组的起始指针,初始值为0,都指向第一个元素;
进入循环后,首先判断起始指针是否已经到数组的最后,如果是,表示其中一个数组已经判断完了,只需返回剩余数组的第k个元素即为结果
如果k=1,这时两个数组都还没有判断完,这时只需返回剩余数组的最小元素(第一个),即两个数组第一个元素的最小值;
主要部分:
首先获取接下来需要判断的index,这个index不能超过数组的最大值,所以需要判断一下,相应的k也就不能直接写成k-=k/2,因为判断完舍去的元素个数不一定为k/2,新的起始指针设为index+1,因为判断完后,连位置为index的元素也一并舍去了,所以需要从下一个元素开始判断
具体的原理可以直接看下面的链接
时间复杂度为O(logn)的算法要先考虑二分法,这种方法复杂的地方就在于奇偶判断这部分,建议画图,举例解决
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-s-114/