这是我参与更文挑战的第4天,活动详情查看: 更文挑战
第4天,继续挑战第4题。这题虽然等级是困难,但是看到给的数据量只有1000,AC过去不算难,但是要达到进阶不容易。
题目
给定两个大小分别为 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
思路
这题要求中位数,如果总个数是奇数,很好理解就是最中间位置的那个数。如果是偶数,就需要拿最中间的2个数来求平均数,实例2也有写。由于这2个数组是有序的,可以用插值排序的方法把2个数组合并成一个大数组,再来求中位数,这样的思路非常清晰,时间复杂度是O(m+n),空间复杂度是O(m+n)。一个优化点是,由于我们用插值法和合并2个有序数组,其实我们只要合并到一半就得到中位数了,不需要完成合并完成,这样时间复杂度是O((m+n)/2),其实还是O(m+n),不过由于就不需要存着新的合并数组,空间复杂度降为O(1)。
注意
注意点就是插值过程中,一个数组已经被遍历完的情况,同理也要注意其中1个数组可能一开始就为空的情况。
Java版本代码
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
int len = len1 + len2;
if (len % 2 == 0) {
// 如果总长度是偶数,需要找到中间的2个数,然后取平均数
int index = len / 2;
int start1 = 0;
int start2 = 0;
// 序号为index-1的数
int mmin = 0;
while (index >= 0) {
if (start1 < len1 && start2 < len2) {
if (nums1[start1] < nums2[start2]) {
if (index == 1) {
mmin = nums1[start1];
} else if (index == 0) {
return avg(mmin, nums1[start1]);
}
start1++;
} else {
if (index == 1) {
mmin = nums2[start2];
} else if (index == 0) {
return avg(mmin, nums2[start2]);
}
start2++;
}
} else if (start1 < len1) {
if (index == 1) {
mmin = nums1[start1];
} else if (index == 0) {
return avg(mmin, nums1[start1]);
}
start1++;
} else {
if (index == 1) {
mmin = nums2[start2];
} else if (index == 0) {
return avg(mmin, nums2[start2]);
}
start2++;
}
index--;
}
} else {
// 如果总长度是奇数,最中间位置的数就是中位数
int index = len / 2;
int start1 = 0;
int start2 = 0;
while (index >= 0) {
if (start1 < len1 && start2 < len2) {
if (nums1[start1] < nums2[start2]) {
if (index == 0) {
return nums1[start1];
}
start1++;
} else {
if (index == 0) {
return nums2[start2];
}
start2++;
}
} else if (start1 < len1) {
if (index == 0) {
return nums1[start1];
}
start1++;
} else {
if (index == 0) {
return nums2[start2];
}
start2++;
}
index--;
}
}
return -1;
}
private static double avg(int a, int b) {
return (a + b) / 2.0;
}
}