问题
给定两个大小为 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 = [2], nums2 = [] 输出:2.00000
提示:
nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-10^6 <= nums1[i], nums2[i] <= 10^6
思路一
中位数是中间大的那个数。假设数组长度为len,如果len为偶数,则数组下标为len/2 -1, len/2的平均数就是中位数;如果len为奇数,则数组下标为len/2的数字就是中位数。
这样可以像归并排序一样,当归并到len/2 + 1个数字就可以了。由于len有偶数的情况,需要记录前一个数字。
需要注意的是,如果某一个数组是空数组的话,需要单独处理。
代码一
public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len1 = nums1.length, len2 = nums2.length;
int len = len1 + len2;
int targetIndex = len / 2;
int last = 0, current = 0;
int i = 0, j = 0;
for (int k = 0; k <= targetIndex; k++) {
last = current;
// j >= len2说明第二个数组已经到末尾了,防止数组2越界
if (i < len1 && (j >= len2 || nums1[i] < nums2[j])) {
current = nums1[i];
i++;
} else {
current = nums2[j];
j++;
}
}
if (len % 2 == 0) {
return (last + current) / 2.0;
} else {
return current;
}
}
}
复杂度一
时间复杂度:O(m+n)
空间复杂度:O(1)
思路二
使用归并排序,在排序后的数组中找到中位数。
代码二
public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
int len = len1 + len2;
int[] nums = new int[len];
int i = 0, j = 0;
for (int k = 0; k < len; k++) {
if (i < len1 && (j == len2 || nums1[i] < nums2[j])) {
nums[k] = nums1[i++];
} else {
nums[k] = nums2[j++];
}
}
return median(nums);
}
private double median(int[] nums) {
int len = nums.length;
int mid = len / 2;
if (len % 2 == 0) {
return (nums[mid-1] + nums[mid]) / 2.0;
} else {
return nums[mid];
}
}
}
复杂度二
时间复杂度:O(m+n)
空间复杂度:O(m+n)
硬广告
欢迎关注公众号:double6