描述
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。
进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?
提示:
- nums1.length == m
- nums2.length == n
- 0 <= m <= 1000
- 0 <= n <= 1000
- 1 <= m + n <= 2000
- -10^6 <= nums1[i], nums2[i] <= 10^6
思路1
- 这道题难度为hard主要是因为有log(m+n)的时间复杂度要求,如果没有这个要求的话就很简单了。
- 比如,直接合并两个数组,然后进行一次排序,就找到了中位数。但这样没有用到“两个数组有序”这个条件,且合并+排序操作会导致时间复杂度很高。

解答1
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
nums1.insert(nums1.end(), nums2.begin(), nums2.end());
sort(nums1.begin(), nums1.end());
int size = nums1.size();
double tmp;
if(size%2 == 0){
double a = (nums1[size/2-1] + nums1[size/2]);
tmp = a/2;
}
return (size % 2 == 0) ? tmp : nums1[size/2];
}
};
思路2
前面做过一道合并两个有序数组的题,时间复杂度为O(m+n)。合并后的有序数组直接取中位数的值即可,但是还没到题目要求的log。
思路3:二分查找
- 一般看到O(log)的时间复杂度,一般都是二分查找法。这个思路我没想到,直接看评论区和题解了。
- 在优快云上找到了这篇博客:LeetCode Median of Two Sorted Arrays 在两个已排列的数组中找出中位数。时间复杂度为O(log(min(N,M)),可以参考作者的写法,和题解的做法是一样的。
- 这样时间复杂度就降到了O(min(logM, logN)),其中M和N分别是数组1和数组2的长度。虽然时间复杂度大幅度降低,但让我奇怪的是执行时间相较于思路1并没有减少很多,难道是测试用例不够长?

解答3
class Solution {
public:
int MAX_VALUE = 2147483647; //0x80000000;
int MIN_VALUE = -2147483648; //0x7fffffff;
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int size1 = nums1.size();
int size2 = nums2.size();
int size = size1 + size2;
//交换数组,保证nums1是较短的数组,减少查找次数
if(size1 > size2) return findMedianSortedArrays(nums2, nums1);
//只有一个nums2数组,直接返回中位数即可
if(size1 == 0)
//涵盖了奇数个数和偶数个数的情况
return ((double)nums2[(size2-1) / 2] + (double)nums2[size2 / 2]) / 2;
int cutL = 0, cutR = size1;
int cut1 = 0;//cut1保存当前在数组1的哪个位置前切一刀
int cut2;//cut2保存当前在数组2.........
while(cut1 < size1){
cut1 = (cutR - cutL) / 2 + cutL;//从中间开始对数组1切第一刀,位置在第size1/2前
cut2 = size / 2 - cut1;//那么数组2切的位置也是固定的
double l1 = (cut1 == 0) ? MIN_VALUE : nums1[cut1 - 1];
double l2 = (cut2 == 0) ? MIN_VALUE : nums2[cut2 - 1];
double r1 = (cut1 == size1) ? MAX_VALUE : nums1[cut1];
double r2 = (cut2 == size2) ? MAX_VALUE : nums2[cut2];
if(l1 > r2) cutR = cut1 - 1;
else if(l2 > r1) cutL = cut1 + 1;
else {//找到正确位置
if(size % 2 == 0){//一共偶数个值
double leftMax = (l1 > l2) ? l1 : l2;//左边较大的值
double rightMin = (r1 > r2) ? r2 : r1;//右边较小的值
return (leftMax + rightMin) / 2;
}else{//奇数个,切完后左边总数比右边少一个,中位数必定出现在右边
return (r1 < r2) ? r1 : r2;
}
}
}
return 0;
}
};
给定两个正序数组nums1和nums2,找到它们的中位数。要求时间复杂度为O(log(m+n))。通过二分查找法实现,参考优快云上的博客,时间复杂度降低到O(min(logM, logN)),但实际执行时间可能并不显著减少。"
126488027,7435057,配置无线网络802.1X RADIUS认证,"['WLAN', '网络配置', '无线网络', '认证方案', 'RADIUS服务器']


被折叠的 条评论
为什么被折叠?



