2-找两个有序数组的中位数
2017-03-19 18:54
225 查看
0. 题目
题目: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)).
1. 步骤
假设这两个数组的大小分别为m (nums1)和n (nums2)。首先要有最差的解法,即不考虑时间复杂度O(log(m+n))
解法1-思路:使用合并排序中的merge函数,将两个有序数组合并为一个有序数组,而后返回中位数。此时时间复杂度为O(n+m)
其次,再找较优秀的解法
解法2-思路: 时间复杂度为O(log(m+n),两个数组又是有序的数组,故考察的应该是二分查找;
2. 优化思路
题目其实可以拓展为求两个有序数组第k大元素。假设我们有一个函数可以用来返回合并数组的第k大元素,那么就变成了这样:如果 m+n 是奇数,则找合并数组的第
(m+n)/2大元素
如果 m+n 是偶数,则返回
(m+n)/2大元素和第
(m+n)/2+1大元素
如何求两个有序数组的第
k大元素? 我们可以每次取两个数组的前
k/2个元素,比较两个数组的第
k/2个元素的大小,而后决定删除哪一个数组的前
k/2个元素。因为第
k大元素肯定不可能在第
2/k个元素较小的那个数组的前
k/2个元素之中。算法步骤如下:
每一次取nums1和nums2的前k/2个元素,比较
nums1[k/2]与
nums2[k/2]的大小
if(nums1[k/2] <= nums2[k/2] ),则删除
nums1[0~k/2]之间的元素,第
k个元素不可能在该区间,同时也要更新
k
反之,则删除
nums2[0~k/2]之间的元素,更新
k
递归地进行上述操作,直到找到第
k个元素为止
3. 容易出错的地方
基本上就是递归的终止条件,非常容易出错。要注意如下几点:当
nums1.size()<k/2和
nums2.size()<k/2的时候,要如何处理?
当
k==1的时候要如何处理?
上述两个条件都不满足的时候要如何处理?
每一删除数组中一个区间,数组的边界如何处理?
4. 代码如下
方法1:class Solution1 { //时间复杂度为o( size(x1) + size(x2) ) public: void merge(vector<int> &des,vector<int>&x1,vector<int>&x2){ int _size=des.size(); int i,j,k; i=0; j=0; k=0; while(i<x1.size() && j<x2.size() ){ if(x1[i]<x2[j]){ des[k++]=x1[i++]; }else{ des[k++]=x2[j++]; } } if(i<x1.size()) { for(;i<x1.size();++i){ des[k++]=x1[i]; } }else{ for(;j<x2.size();++j){ des[k++]=x2[j]; } } } double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { vector<int> des(nums1.size()+nums2.size(),0); merge(des,nums1,nums2); int middle=( des.size()-1 )/2; if(des.size()%2==0){ return double(des[middle]+des[middle+1])/2; }else{ return des[middle]; } } };
方法2:
class Solution2 { public: // 非递归形式 边界这块不好写 不用考虑奇数偶数问题只需要返回一个值就好了 int findKth(vector<int>&nums1,int low1,int high1,vector<int>&nums2,int low2,int high2,int k){ if(low1>high1) return nums2[low2+k-1]; if(low2>high2) return nums1[low1+k-1]; if(k==1) { return min(nums1[low1],nums2[low2]); } int mid=k/2-1; if( (low1+mid)>high1){ if( nums1[high1]<=nums2[low2+mid] ){ k=k-(high1-low1+1); return nums2[low2+k-1]; }else{ k=k-(mid+1); low2 += mid+1; return findKth(nums1,low1,high1,nums2,low2,high2,k); } } if((low2+mid)>high2 ){ if( nums2[high2]<=nums1[low1+mid] ){ k=k-(high2-low2+1); return nums1[low1+k-1]; }else{ k=k-(mid+1); low1 += mid+1; return findKth(nums1,low1,high1,nums2,low2,high2,k); } } if( nums1[ low1 + mid ] <= nums2[ low2 + mid ]) { low1=low1+mid+1; k=k-(mid+1); }else{ low2=low2+mid+1; k=k-(mid+1); } return findKth(nums1,low1,high1,nums2,low2,high2,k); } double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int _size=nums1.size()+nums2.size(); int mid=(_size+1)/2; double res=0; if(_size%2==0){ res=(double)findKth(nums1,0,nums1.size()-1,nums2,0,nums2.size()-1,mid); cout<<res<<endl; res += (double)findKth(nums1,0,nums1.size()-1,nums2,0,nums2.size()-1,mid+1); res=res/2; }else{ res=(double)findKth(nums1,0,nums1.size()-1,nums2,0,nums2.size()-1,mid); } return res; } };
相关文章推荐
- 4. Median of Two Sorted Arrays 两个有序数组的中位数
- 两个有序数组的中位数 【算法】
- 【Leetcode】两个有序数组的中位数
- 【分步详解】两个有序数组中的中位数和Top K问题
- Median of Two Sorted Arrays---两个有序数组查找中位数
- 求两个等长有序数组的中位数的logN算法 分治法
- LeetCode OJ 之 Median of Two Sorted Arrays(两个有序数组的中位数)
- [LeetCode] Median of Two Sorted Arrays 两个有序数组的中位数
- [LeetCode] 求两个有序数组的中位数
- 求两个有序数组的中位数
- 两个有序数组的中位数
- 求两个有序数组的中位数或者第k小元素(转载)
- [nowCoder] 两个长度相同有序数组的中位数
- 求两个有序数组的中位数
- 关于在一个序列中寻找中位数和第K大的数(在两个等长有序数组中寻找中位数)
- Java实现O(log(n+m))两个有序数组中第K大元素或中位数
- 给定两个有序数组,找出合并之后的数组中位数
- 求两个有序数组的中位数(4. Median of Two Sorted Arrays)
- 4.求两个有序数组的中位数
- [leetcode] Median of Two Sorted Arrays 寻找两个有序数组的中位数