两个排序数组的中位数
题目:给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。
请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。
输入:nums1 = [1, 3];nums2 = [2]
输出:2.0
这道题一个比较通俗的思路是:将两个已排序的序列,遍历一次,排成一个总的序列,然后再找出其中位数。但是!这样思路的算法时间复杂度是O(m+n)并不是O( log(m+n) )
给出一个O( log(m+n) )的思路:1、找两个已排序的中位数,其实可以看成找第k个小的数字
2、由于题目要求的时间复杂度为O( log(m+n) )看到带log的时间复杂度,第一反应是二分法。
3、于是,利用下面的方法:
4、每次比较 nums1[k/2 - 1] 和 nums2[k/2 - 1] 的大小,删除较小的数列的前k/2个数字,直到k的值为1时,这时,只要比较nums1和nums2的第一个数字即可
/*
具体思路:利用二分法,每次删除前k/2个数字,直到k=1,然后比较一下nums1和nums2数组中的最小值即可
*/
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
//sumNum为nums1和nums2的总个数和
int sumNum = nums1.size() + nums2.size();
//用于判断总个数是奇数还是偶数,如果是奇数,那么中位数只有1个,如果是偶数,那么中位数有2个
bool isOdd;
double avgNum;
int k;
if ((sumNum & 1) == 1){
//奇数中的中位数是 总数/2+1
k = sumNum / 2 + 1;
isOdd = true;
}
else{
k = sumNum / 2;
isOdd = false;
}
while (k != 1){
//这里分情况讨论,如果k/2比整个nums1都大,那么只判断nums1的最后一个数字和nums2的k/2个数即可,
if ((k / 2)>nums1.size()){
if (nums1.size() == 0){
break;
}
if (nums1[nums1.size() - 1]<nums2[k / 2 - 1]){
k = k - nums1.size();
nums1.clear();
}
else{
nums2.erase(nums2.begin(), nums2.begin() + k / 2);
k = k - (k / 2);
}
}
//如果k/2比整个nums2都大,那么只判断nums2的最后一个数字和nums1的k/2个数即可,
else if ((k / 2)>nums2.size()){
if (nums2.size() == 0){
break;
}
if (nums2[nums2.size() - 1]<nums1[k / 2 - 1]){
k = k - nums2.size();
nums2.clear();
}
else{
nums1.erase(nums1.begin(), nums1.begin() + k / 2);
k = k - (k / 2);
}
}
//如果nums1和nums2中个数都大于k/2,那么直接判断nums1[k/2]和nums2[k/2]即可,这里nums1[k/2-1]是因为数组是从0开始计数的
else{
if (nums1[k / 2 - 1] <= nums2[k / 2 - 1]){
nums1.erase(nums1.begin(), nums1.begin() + k / 2);
}
else{
nums2.erase(nums2.begin(), nums2.begin() + k / 2);
}
k = k - (k / 2);
}
}
//根据奇偶来判断中位数的个数是2个还是1个
if (isOdd){
if (nums1.size() == 0){
avgNum = nums2[k - 1];
}
else if (nums2.size() == 0){
avgNum = nums1[k - 1];
}
else{
if (nums1[k - 1]<nums2[k - 1]){
avgNum = nums1[k - 1];
}
else{
avgNum = nums2[k - 1];
}
}
}
else{
if (nums1.size() == 0){
avgNum = (nums2[k - 1] + nums2[k]) / 2.0;
}
else if (nums2.size() == 0){
avgNum = (nums1[k - 1] + nums1[k]) / 2.0;
}
else{
//对于偶数这边的计算要比较当心,会出现几种情况:
//1、nums1[k-1]和nums1[k]都小于nums2[k-1],那么就取nums1[k-1]和nums1[k]的平均即可
//2、nums2[k-1]和nums2[k]都小于nums1[k-1],那么就取nums2[k-1]和nums2[k]的平均即可
//3、nums1[k-1]和nums2[k-1]是相对nums1[k-1]、nums1[k]、nums2[k-1]、nums2[k]这4个数字中最小的2个,那么取nums1[k-1]和nums2[k-1]的平均即可
if (nums1[k - 1]<nums2[k - 1]){
if (nums1.size() - 1 >= k){
if (nums1[k]<nums2[k - 1]){
avgNum = (nums1[k - 1] + nums1[k]) / 2.0;
}
else{
avgNum = (nums1[k - 1] + nums2[k - 1]) / 2.0;
}
}
else{
avgNum = (nums1[k - 1] + nums2[k - 1]) / 2.0;
}
}
else{
if (nums2.size() - 1 >= k){
if (nums1[k - 1]<nums2[k]){
avgNum = (nums1[k - 1] + nums2[k - 1]) / 2.0;
}
else{
avgNum = (nums2[k - 1] + nums2[k]) / 2.0;
}
}
else{
avgNum = (nums1[k - 1] + nums2[k - 1]) / 2.0;
}
}
}
}
return avgNum;
}
};