/**
* 给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
* 示例 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.length == m
* nums2.length == n
* 0 <= m <= 1000
* 0 <= n <= 1000
* 1 <= m + n <= 2000
* -106 <= nums1[i], nums2[i] <= 106
* 输入:nums1 = [2], nums2 = []
* 输出:2.00000
* 力扣(LeetCode)https://leetcode-cn.com/problems/median-of-two-sorted-arrays
*
*/
public class FindMedianOrdered {
public static void main(String[] args) {
int[] nums1 = {3,5};
int[] nums2 = {1,2};
double ret = findMedianSortedArrays2(nums1, nums2);
System.out.println(ret);
}
/**
* 简单粗暴,先将两个数组合并,两个有序数组的合并也是归并排序中的一部分。然后根据奇数,还是偶数,返回中位数。
* 时间复杂度:遍历全部数组 (m+n)(m+n)
* 空间复杂度:开辟了一个数组,保存合并后的两个数组 O(m+n)O(m+n)
* 该解法并不算太优雅,但最容易理解
*/
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
int[] nums;
int m = nums1.length;
int n = nums2.length;
nums = new int[m + n];
if (m == 0) {
if (n % 2 == 0) {
return (nums2[n / 2 - 1] + nums2[n / 2]) / 2.0;
} else {
return nums2[n / 2];
}
}
if (n == 0) {
if (m % 2 == 0) {
return (nums1[m / 2 - 1] + nums1[m / 2]) / 2.0;
} else {
return nums1[m / 2];
}
}
int count=0,i=0,j=0;
nums = new int[m+n];
while(count!=(m+n)){
if(i==m){
while(j!=n){
nums[count++] = nums2[j++];
}
break;
}
if(j==n){
while(i!=m){
nums[count++] = nums1[i++];
}
break;
}
if(nums1[i] < nums2[j]){
nums[count++] = nums1[i++];
} else {
nums[count++] = nums2[j++];
}
}
if (count % 2 == 0) {
return (nums[count / 2 - 1] + nums[count / 2]) / 2.0;
} else {
return nums[count / 2];
}
}
/**
*
* 时间复杂度:遍历 len/2+1 次,len=m+n,所以时间复杂度依旧是 O(m+n)O(m+n)。
* 空间复杂度:我们申请了常数个变量,也就是 m,n,len,left,right,aCursor,bCursor 以及 i。总共 8 个变量,所以空间复杂度是 O(1)O(1)。
*/
public static double findMedianSortedArrays2(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
int len = m+n;
int aCursor = 0, bCursor = 0;
int left = -1, right = -1;
for (int i=0;i<=len/2;i++) {
left = right;
if(aCursor<m && (bCursor>=n
|| nums1[aCursor] < nums2[bCursor])){
right = nums1[aCursor++];
}else {
right = nums2[bCursor++];
}
}
if((len & 1) == 0)
return (left + right) / 2.0;
else
return right;
}
}