求两个有序非等长数组中位数
2016-01-14 16:38
387 查看
本博客所用算法是受另外一篇博客所启发,但该博主给出的代码很多边界条件和n+m为偶数的情况未考虑到,这里我做了一定的完善。
原题如下:
There are two sorted arrays nums1 and nums2 of
size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
大致意思是有两个有序数组nums1和nums2,长度分别为m和n,要求找到它们合并之后的中位数并且总共的是时间效率应该为O(log(m+n))。
先看看中位数的定义,一个长度为n的数组,如果n为奇数,则数组中有(n-1)/2个元素比中位数小。如果n为偶数,则数组张有n/2个元素比上中位数小,n/2-1个元素比下中位数小。
题目要求从nums1和nums2中找出中位数,我们可以先从nums1中查找。先考虑n+m为奇数的情况,c=(m+n-1)/2,我们的查找区间应该为[nums1[0],nums1[m-1]],我们取其中间的数nums1[p],与nums2[c-p-1]和nums2[c-p]做比较。
这里需要注意的是,如果p>c,说明num1[p]偏大,我们应该调整查找区间为[nums1[0],nums1[p-1]]。如果p==c,并且此时nums1[p]<=nums2[0],那么nums1[p]就是我们所要找的中位数,否则查找区间改为[nums1[0],nums1[p-1]]。
只剩下p<c的情况需要讨论了,如果num1[p]<nums2[c-p-1],说明num1[p]偏小,查找区间改为[num1[p+1],nums1[m-1]]。否则再讨论(c-p)和n的大小关系来确定查找范围。
在n+m为偶数的情况,只需要把c加1,求两次结果即可。
代码如下,已通过测验。本人刚学习C++,写的可能比较繁琐,望见谅。
原题如下:
There are two sorted arrays nums1 and nums2 of
size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
大致意思是有两个有序数组nums1和nums2,长度分别为m和n,要求找到它们合并之后的中位数并且总共的是时间效率应该为O(log(m+n))。
先看看中位数的定义,一个长度为n的数组,如果n为奇数,则数组中有(n-1)/2个元素比中位数小。如果n为偶数,则数组张有n/2个元素比上中位数小,n/2-1个元素比下中位数小。
题目要求从nums1和nums2中找出中位数,我们可以先从nums1中查找。先考虑n+m为奇数的情况,c=(m+n-1)/2,我们的查找区间应该为[nums1[0],nums1[m-1]],我们取其中间的数nums1[p],与nums2[c-p-1]和nums2[c-p]做比较。
这里需要注意的是,如果p>c,说明num1[p]偏大,我们应该调整查找区间为[nums1[0],nums1[p-1]]。如果p==c,并且此时nums1[p]<=nums2[0],那么nums1[p]就是我们所要找的中位数,否则查找区间改为[nums1[0],nums1[p-1]]。
只剩下p<c的情况需要讨论了,如果num1[p]<nums2[c-p-1],说明num1[p]偏小,查找区间改为[num1[p+1],nums1[m-1]]。否则再讨论(c-p)和n的大小关系来确定查找范围。
在n+m为偶数的情况,只需要把c加1,求两次结果即可。
代码如下,已通过测验。本人刚学习C++,写的可能比较繁琐,望见谅。
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int result1 = 0; int result2=0; int m = nums1.size(); int n = nums2.size(); if (n == 0) { if (m % 2 == 1) { return nums1[(m + 1) / 2 - 1]; } else { return (nums1[m / 2 - 1] + nums1[m / 2]) / 2.0; } } if (m == 0) { if (n % 2 == 1) { return nums2[(n + 1) / 2 - 1]; } else { return (nums2[n / 2 - 1] + nums2[n / 2]) / 2.0; } } if ((n + m) % 2 == 1) { return findmedian(nums1, nums2, 0, m - 1); } else { result1 = findmedian(nums1, nums2, 0, m - 1); result2 = findmedian_1(nums1, nums2, 0, m - 1); return (result1 + result2) / 2.0; } } int findmedian(vector<int>& nums1, vector<int>& nums2, int begin, int end) { int m = nums1.size(); int n = nums2.size(); double c = ceil((double)(n + m) / 2.0) - 1; int p = ceil((double)(begin + end) / 2.0); if (nums2[0] >= nums1[m - 1]) { if (c >= m) return nums2[c - m]; if (c < m) return nums1[c]; } if (nums1[0] >= nums2[n - 1]) { if (c >= n) return nums1[c - n]; if (c < n) return nums2[c]; } if (begin>end) return findmedian(nums2, nums1, 0, n - 1); if (c<p) { return findmedian(nums1, nums2, begin, p - 1); } else if((c-p)>0) { if (nums1[p]<nums2[c - p - 1]) return findmedian(nums1, nums2, p + 1, end); else{ if ((c - p) >n) return findmedian(nums1, nums2, p + 1, end); else { if((c-p)==n) { if(nums1[p]>=nums2[n-1]) return nums1[p]; else return findmedian(nums1,nums2,p+1,end); } else if(nums1[p]>=nums2[c-p-1]&&nums1[p]<=nums2[c-p]) return nums1[p]; else if(nums1[p]>nums2[c-p]) return findmedian(nums1, nums2, begin, p - 1); } } } else if(c==p) { if(nums1[p]<=nums2[0]) return nums1[p]; else return findmedian(nums1, nums2, begin, p - 1); } } int findmedian_1(vector<int>& nums1, vector<int>& nums2, int begin, int end) { int m = nums1.size(); int n = nums2.size(); double c = ceil((double)(n + m) / 2.0); int p = ceil((double)(begin + end) / 2.0); if (nums2[0] >= nums1[m - 1]) { if (c >= m) return nums2[c - m]; if (c < m) return nums1[c]; } if (nums1[0] >= nums2[n - 1]) { if (c >= n) return nums1[c - n]; if (c < n) return nums2[c]; } if (begin>end) return findmedian_1(nums2, nums1, 0, n - 1); if (c<p) { return findmedian_1(nums1, nums2, begin, p - 1); } else if((c-p)>0) { if (nums1[p]<nums2[c - p - 1]) return findmedian_1(nums1, nums2, p + 1, end); else{ if ((c - p) >n) return findmedian_1(nums1, nums2, p + 1, end); else { if((c-p)==n) { if(nums1[p]>=nums2[n-1]) return nums1[p]; else return findmedian_1(nums1,nums2,p+1,end); } else if(nums1[p]>=nums2[c-p-1]&&nums1[p]<=nums2[c-p]) return nums1[p]; else if(nums1[p]>nums2[c-p]) return findmedian_1(nums1, nums2, begin, p - 1); } } } else if(c==p) { if(nums1[p]<=nums2[0]) return nums1[p]; else return findmedian_1(nums1, nums2, begin, p - 1); } }
相关文章推荐
- Java:String和Date、Timestamp之间的转换
- Https与Http,SSL,DevOps, 静态代码分析工具,RFID, SSH, 非对称加密算法(使用最广泛的一种是RSA), 数字签名, 数字证书
- Js保存信息到缓存中
- 自定义控件点滴2(setColorFilter)
- Java 网络编程(四) InetAddress类
- 聊聊企业老板对管理软件态度的一点感悟
- select,poll,epoll的区别
- 调用隐式intent需要注意的地方。
- Xcode编译Undefined symbols for architecture xxx 错误总结
- mysql事务知识分享
- C语言技巧
- C语言 随机数
- Java继承与初始化
- 详解C++编程中的sizeof运算符与typeid运算符
- Java 网络编程(三) 创建和使用URL访问网络上的资源
- mysqlmap-config.xml
- Java 网络编程(二) 两类传输协议:TCP UDP
- C语言system命令
- 测量控件的高度
- 把笔记本游戏调成全屏