思路一(暴力):

  当看到这个题目的时候可能会觉的是不是系统高估了这个题目,这个这么简单,只需要将两个数组合并,排序然后合并就好了。这样做确实可以求出中位数,但是并不能说是完成题目的要求,因为题目的要求时间复杂度是O(log(m + n)),这个暴力算法的时间复杂度很明显是O(m+n),可以有兴趣的可以测一下,这个算法不是本博客的重点,这里不多赘述,代码如下:

    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {double ret = -1;vector<double> buff;//合并两个数组for (auto e : nums1)buff.push_back(e);for (auto a : nums2)buff.push_back(a);//将合并后的结果进行排序sort(buff.begin(), buff.end());int size3 = buff.size();//获取中位数if (size3 % 2 == 0){ret = ((buff[size3 / 2] + buff[size3 / 2 - 1]) / 2);}elseret = buff[size3 / 2];return ret;
}
思路二:分治+二分查找
题目解析:

  这个题目简单来说就是如果将两个已经排序的数组合并为一个虚拟数组,求出这个虚拟数组的中位数即可。

解题思路:

  1、这道题最主要的就是切(cut),怎么将数组切成合适的两段是关键,对于一个数组来说在数组的中间将其切成两段,这时候就要分情况讨论,如果是偶数个,中位数就是切点的两边第一个数的平均值,如果是奇数个,中位数就是切点右边的第一个数,比如说1 2 3 4 5,在中间的位置将这个数组切成两段:1 2 \ 3 4 5,很显然,中位数就是3,如果是1 2 3 4,那么就切成了1 2 \ 3 4,很显然中位数就是(2+3)/2 = 2.5。
  2、理解了切的思想,接下来就开始在两个数组中进行切,这时候就用到了分治思想。
  怎么分?
  题目中要求的时间复杂度为 O(log(m + n)),很容易想到的方法就是二分,现在有两个数组,要对那个数组进行二分合适?由于找的是中位数,那么这个数字的两边的元素个数是相等的,所以只需要确定一个数组中的两边元素,两一个数组的对应的补上去就可以了,为了提高效率,要选择最短的数组做二分查找。
  怎么治?
  这个也很容易,只需要分别比较两个数组切点两边的数就可以,假设数组1中切点两边的元素为L1,R1,数组2中切点两边的元素为:L2,R2,切完之后有三种情况:
  1)L1>R2 ,说明数组1的左半边比数组2的右半边大,应该让cut向左移,才能使数组一中较多的数被分配到右边。
  2)L2>R1 ,说明数组2的左半边比数组1的右半边大,应该让cut向右移,才能使数组一中较多的数被分配到左边。
  3)其他情况(L1<=R2 L2<=R1),cut的位置是正确的,可以停止查找,输出结果。
3.特殊情况
分析完了正常的情况,那么就要分析一下特殊情况;
  1)如果有一个数组是空的,直接返回另一个不为空的数组中的中位数
  2)如果两个数组元素的个数相等,并且两个数组的中位数相等,直接返回其中一个中位数。
  3)有可能在进行二分查找的时候出现了数组越界的情况,只需要定义一个最大值和一个最小值,这样可以按照正常的情况来处理了。
4、输出结果分情况
  两个数组的输出情况和之前的一个数组的输出大致是一样,只是添加了选择性,如果是偶数个,输出(min(L1, L2) + min(R1, R2))/2,如果是奇数个,输出min(R1, R2)。

图解思路:


  这里只对不越界和不为空的数组进行解析。

代码解析:
class Solution {public:double MedNum(vector<int>& num){double ret;size_t size = num.size();if(size == 1)return num[0];int med = size / 2;if (size% 2 == 0){ret =  ((double)(num[med] + num[med - 1]) / 2);}elseret = num[med];return ret;}double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2){double ret = -1;//定义最小数和最大数const int BDL_MIN_ = 0x80000000;const int BDL_MAX_ = 0x7fffffff;//情况一://如果这两个数组中有一个是空的,直接返回另一个的中位数即可if (nums1.empty())return MedNum(nums2);else if (nums2.empty())return MedNum(nums1);//情况二://如果两个数组分别的中位数相等,那么这两个数的中位数就是这个中位数int size1 = nums1.size();  //数组一的长度int size2 = nums2.size();  //数组二的长度if(size1 == size2){Med1 = MedNum(nums1);Med1 = MedNum(nums1);if(Med1 == Med2)return Med1;}//情况三://使用分治思想,二分查找方法int size0 = size1 + size2; //两个数组的总长度//为了效率,要选择最短的数组做二分查找,使数组一为最短//如果第一个数组比第二个数组长,就要使两个数组交换//但是swap的时间复杂度使O(N+M),所以将两个数组交换位置再调一次函数即可if (size1 > size2)return findMedianSortedArrays(nums2, nums1);//设置二分查找的范围int cutL = 0;int cutR = size1;//这里将cut1初始为数组1的中位数int cut1 = (size1 - 1) / 2;while (cut1 <= size1){cut1 = (cutR - cutL) / 2+cutL;                           //在数组1中找cut1切点(二分)int cut2 = (size0 / 2) - cut1;                           //在数组2中找cut2切点//这里不用size2直接确定切点,是因为将两个数组进行了虚拟合并,使用虚拟数组的总数size0找中间点,然后将属于数组一的部分减去,就是cut2在数组2中的切点,可以结合上面的图片捋一下。//确定L1,L2,L3,L4的值,并判断当前的切点有没有越界          double L1 = (cut1 == 0) ? BDL_MIN_ : nums1[cut1-1];double R1 = (cut1 == size1) ? BDL_MAX_ : nums1[cut1];double L2 = (cut2 == 0) ? BDL_MIN_ : nums2[cut2-1];double R2 = (cut2 == size2) ? BDL_MAX_ : nums2[cut2];//如果L1>R2,则cut1应该向左移,才能使数组1较多的数被分配到右边。if (L1 > R2)cutR = cut1-1;//如果L2 > R1,则cut1应该向右移,才能使数组1较多的数被分配到左边。else if (L2 > R1)cutL = cut1+1;//其他情况就是L1<=R2 L2<=R1,说明当前cut1和cut2的位置就是中位数的位置了else{//如果两个数组中加起来的元素数量是偶数,那么中位数就应该是两个中位数的平均值if (size0 % 2 == 0){L1 = max(L1, L2);R1 = min(R1, R2);ret = (L1 + R1) / 2;return ret;}//如果两个数组中元素的数量是奇数,中位数就是当前位置的右值else{ret = min(R1, R2);return ret;}}}return ret;}
};

如果有什么问题可以在评论区留言!

寻找两个有序数组的中位数(虚拟数组图文详解)相关推荐

  1. 骨干云池服务器SATA盘的RAID配置,用两块硬盘组建RAID0磁盘阵列简单教程(图文详解)...

    传统硬盘由于工作原理的限制,在性能上的提升非常缓慢.而固态硬盘价格昂贵,短时间内难以被普通用户接受.因此采用两块或多块硬盘组建RAID磁盘阵列也成为了目前比较有性价比的硬盘性能提升解决方案.之前我们也 ...

  2. 算法--------------------寻找两个有序数组的中位数

    题目描述 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2.请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)).你可以假设 nums1 和 num ...

  3. 两个有序数组的中位数 python_Python寻找两个有序数组的中位数实例详解

    Python寻找两个有序数组的中位数 审题: 1.找出意味着这是一个查找算法题 2.算法复杂度log级别,就是提示你是二分查找 3.二分查找实现一般为递归 (1)递归包括递归体 (2)终止条件 思路: ...

  4. LeetCode4. 寻找两个有序数组的中位数

    4. 寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假 ...

  5. 20191016:(leetcode习题)寻找两个有序数组的中位数

    寻找两个有序数组的中位数 题目 大致思路 代码实现 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log( ...

  6. (JS)寻找两个有序数组的中位数

    寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 n ...

  7. Python寻找两个有序数组的中位数

    Python寻找两个有序数组的中位数 审题: 找出意味着这是一个查找算法题 算法复杂度log级别,就是提示你是二分查找 二分查找实现一般为递归 (1)递归包括递归体 (2)终止条件 思路: 定理: 有 ...

  8. 力扣寻找两个有序数组的中位数

    寻找两个有序数组的中位数 要求 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假 ...

  9. LeetCode(Python实现)—寻找两个有序数组的中位数

    4.寻找两个有序数组的中位数 题目大意 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). ...

  10. 分享一道力扣困难题~寻找两个有序数组的中位数(Java)

    目录 解题思路1 具体代码 解题思路2 具体代码 题目描述:给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的 中位数 .算法的时间复杂 ...

最新文章

  1. Leetcode-435:无重叠区间
  2. android 文字路径,Android自定义控件:路径及文字
  3. 只有一个显示器但是显示两个显示器_小米34寸曲面显示器深度体验 办公体验极佳 但是还有个大弱点...
  4. Rabbitmq如何设置优先级队列?如何限流?如何重试?如何处理幂等性?
  5. 第四篇: UpdatePanel 控件--触发机制Triggers
  6. php将汉字转换为拼音和得到词语首字母(一)
  7. Software--Spring Boot--Contact 项目初期
  8. VSCode:vs code不识别wxss小程序相关文件
  9. ubuntu 出错 /etc/sudoers is world writable
  10. erp系统实施方案会遇到哪些问题?
  11. 使用matplotlib画对数函数图像
  12. STM32f407 DCMI方式驱动 OV2640
  13. 软件测试的需求人才越来越多,为什么大家还是不太愿意走软件测试的道路?
  14. [转]c# 语音卡控制--语音卡电话呼叫系统
  15. 依据前端传递的数字等生成二维码图片
  16. unbuntu 安装虚拟环境 virtualenv和virtualenvwrapper
  17. Linux LTP (一)
  18. PyCon 2011 - Hidden Treasures of the Python Standard Library - 获得夏时令标识符
  19. 全球十大汽车轮胎排名韩泰轮胎:冬季轮胎安全须知
  20. 九度oj-1158-买房子

热门文章

  1. SQL 判断字段是否为中文、字母、数字
  2. 理解G1 Remember Set(RSet)
  3. go swag常用注释
  4. 致敬最美逆行者网页设计作品 大学生抗疫感动专题网页设计作业模板 疫情感动人物静态HTML网页模板下载
  5. 115.n阶方阵求逆
  6. mybatis之(Oracle,MySql)批量更新
  7. 【oiClass 2085】马(排序,DP)
  8. 2022机修钳工(高级)考试题库模拟考试平台操作
  9. 图解什么是一致性哈希算法
  10. HTML5——7个最牛的HTML5移动开发框架