4.求两个已经排好序的数组的中位数
来源:互联网 发布:信捷plc编程软件下载 编辑:程序博客网 时间:2024/06/06 00:18
题目出处:https://leetcode.com/problems/median-of-two-sorted-arrays/
两个已经排好序的数组:nums1 和 nums2, 他们的长度分别是m和n. 求这两个数组的中位数。 要求时间复杂度是O(log(m+n)).
数组的中位数: 就是一排数据从小到大排列后,中间的那个数。 比如 [1, 2, 3, 4, 5], 那中位数就是3. 而 [1, 2, 3, 4, 5,6]的中位数就是 3, 4. 题目要求返回(3+4)/2 =3.5
分析:
1. 如果是一个数组,直接求解好求,直接长度length/2 可直接索引到中位数的位置, 这样可直接求解。
2. 不能合并数组,合并数组的时间复杂度为O(m+n). 与题目要求的O(log(m+n))符.
3. 不考虑复杂度时,最简单的方法是从左到右逐个移动,可很简单的实现快速找到中位数的位置,时间复杂度O((m+n)/2)., 后面会展示算法(算法1)
4. 时间复杂度O(log(m+n))的算法,让我想到二分查询算法, 细想下这问题与方法很像,都是查询,二分查询查询的某个值,而本算法查询的是中位数的位置。 所以决定模仿二分查询来解决这个问题。
算法1 顺序查询法
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int length = nums1.size() + nums2.size(); if(length == 0) return 0; //计算中间数开始的位置索引, 代表需要移动的步数据 int target = length/2; if(length % 2 == 0){ target-=1; } int index1 = 0, index2 = 0; int lastMove = 0; while(index1 < nums1.size() && index2 < nums2.size()){ if(index1 + index2 > target)break; if(nums1[index1] >= nums2[index2]) lastMove = nums2[index2++]; else lastMove = nums1[index1++]; } //中位数在某个列表中 if(index1 + index2 <= target){ int move = target-index1 - index2; //还要移动的步数 if(index1 < nums1.size()){ index1 += move; lastMove = nums1[index1++]; }else{ index2 += move; lastMove = nums2[index2++]; } } if(length % 2 == 1) return lastMove; int second = 0; if(index1 >= nums1.size()) second = nums2[index2]; else if(index2 >= nums2.size()) second = nums1[index1]; else second = nums1[index1] > nums2[index2] ? nums2[index2] : nums1[index1]; return (lastMove + second)/2.0; }
算法2 二分查询法
算法简述:
1. 先计算需要移动的数:less
2. 两个数组同时移动 less/2个数(如果不够, 需要做相应调整)的值分别是data1, data2
3. data1 == data2, 则找到位置
4. data1 != data2, 则移动相应的步少, 同步减少 less的值。
循环结束标志:
less==0, 说明已经移动到中位数位置
有某个数组已经移动到最末,即begin==end. 则在单数组中移位less,就可得到中位数据位置
代码:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2){ if(nums1.size() == 0 && nums2.size() == 0) return 0; int length = nums1.size() + nums2.size(); int less = length>>1; if(length%2 == 0){less -= 1;} int begin1 = 0, end1 = nums1.size(); int begin2 = 0, end2 = nums2.size(); while(1){ //检查是否已经结束 if(less == 0 || begin1 == end1 || begin2 == end2){ if(begin1 == end1) return (length % 2 != 0) ? nums2[begin2+less] : (nums2[begin2+less] + nums2[begin2+less+1])/2.0; if(begin2 == end2) return (length % 2 != 0) ? nums1[begin1+less] : (nums1[begin1+less] + nums1[begin1+less+1])/2.0; //获取第一个数字 int first = 0; if(nums1[begin1] > nums2[begin2]) first = nums2[begin2++]; else first = nums1[begin1++]; // if(length % 2 != 0) return first; int second = 0; if(begin1 == end1) second = nums2[begin2]; else if(begin2 == end2) second = nums1[begin1]; else second = nums2[begin2] > nums1[begin1] ? nums1[begin1]: nums2[begin2]; return (first + second)/2.0; } int mid1 = begin1 + less/2; int mid2 = begin2 + less/2; if(mid1 >= end1){ mid1 = end1 - 1; mid2 = begin2 + less - end1 + begin1; } else if(mid2 >= end2){ mid2 = end2 - 1; mid1 = begin1 + less - end2 + begin2; } if(nums1[mid1] == nums2[mid2]){ less -= mid2 - begin2 + mid1 - begin1; begin2 = mid2; begin1 = mid1; if(less > 0){less--; begin1++;} } else if(nums1[mid1] > nums2[mid2]){ if(mid2 > begin2){ less -= mid2 - begin2; begin2 = mid2; } else{less-=1; begin2+=1;} } else{ if(mid1 > begin1){ less -= mid1 - begin1; begin1 = mid1; } else{less-=1; begin1+=1;} } } return 0;}
- 4.求两个已经排好序的数组的中位数
- 4.求两个有序数组的中位数
- 求两个数组的中位数
- 找出两个已经排好序的数组的中位数
- 【雅虎笔试题】两个已经排好序的数组,找中位数
- 【雅虎笔试题】两个已经排好序的数组,找中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求这两个数组的中位数
- leetcode 求两个排序数组的中位数
- 求两个有序数组的中位数
- 求两个排序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 高效开发iOS -- 那些不为人知的KVC
- 绑定服务 ServiceConnection 没有被回调 TabHost中
- Mac下的常用终端命令与vim常用命令
- python中的 isinstance() 用法总结
- Android M新控件知识整理
- 4.求两个已经排好序的数组的中位数
- 用Linux makeself制作自解压的可执行程序
- Linux的SOCKET编程详解
- 你想在职场上变身成为《欢乐颂》霸气女高管安迪吗?
- PIC单片机之I2C通信(从模式)
- cmake使用示例与整理总结
- HTTP协议详解(真的很经典)
- Android 判断app是否安装
- windows 下 tomcat 内存设置(处理tomcat 内存溢出异常)