您的位置:首页 > 其它

LeetCode 4. Median of Two Sorted Arrays(两个有序数组的中位数)

2018-03-15 19:51 489 查看
题目描述:    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 = [1, 3]
nums2 = [2]
The median is 2.0
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
分析:
    题意:给定两个排好序的数组,大小分别为m和n。求它们的中位数,时间复杂度要求为O(log(m+n))。
    思路:我们来解决一个更一般的问题,求两个有序数组中的第k大的数。总体上有两种做法:①二分法;②深度优先查找(即DFS,这里结合了C++的迭代器vector<int> ::iterator来实现)。需要注意的细节有:①当存在一个或两个数组为空时;②两个数组的元素总数为奇数或者偶数时。两种解法的时间复杂度均为O(log(m+n))。
代码(二分法):
#include <bits/stdc++.h>

using namespace std;

// find k smallest element algorithm: binary search
// T(m, n) = O(log(m+n))
class Solution{
private:
// find the first pos that vec[pos] > target
// the same function as: upper_bound(vec.begin(), vec.end(), target)
int binary_search(vector<int>& vec, int target){
int l = 0, r = vec.size() - 1;
while(l <= r){
int m = (l + r) >> 1;
if(vec[m] > target){
r = m - 1;
}
else if(vec[m] <= target){
l = m + 1;
}
}
return l;
}

double findKSmall(vector<int>& nums1, vector<int>& nums2, int k){
int n1 = nums1.size(), n2 = nums2.size();
int left = min(nums1[0], nums2[0]);
int right = max(nums1[n1 - 1], nums2[n2 - 1]);
// binary search
while(left <= right){
int mid = (left + right) >> 1;
int k1 = binary_search(nums1, mid);
int k2 = binary_search(nums2, mid);
if(k1 + k2 == k){
if(k1 > 0 && nums1[k1 - 1] == mid){
return mid;
}
else if(k2 > 0 && nums2[k2 - 1] == mid){
return mid;
}
else{
right = mid - 1;
}
}
else if(k1 + k2 > k){
right = mid - 1;
}
else if(k1 + k2 < k){
left = mid + 1;
}
}
return left;
}

public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n1 = nums1.size(), n2 = nums2.size();
// Exceptional Case:
if(n1 == 0 && n2 == 0){
return 0.0;
}
else if(n1 == 0 && n2 != 0){
if(n2 & 1){
return (double)nums2[n2 / 2];
}
else{
return ((double)nums2[n2 / 2 - 1] + (double)nums2[n2 / 2]) / 2.0;
}
}
else if(n1 != 0 && n2 == 0){
if(n1 & 1){
return (double)nums1[n1 / 2];
}
else{
return ((double)nums1[n1 / 2 - 1] + (double)nums1[n1 / 2]) / 2.0;
}
}
double ans = 0.0;
if((n1 + n2) & 1){
ans = findKSmall(nums1, nums2, (n1 + n2) / 2 + 1);
}
else{
ans = (findKSmall(nums1, nums2, (n1 + n2) / 2) + findKSmall(nums1, nums2, (n1 + n2) / 2 + 1)) / 2.0;
}
return ans;
}
};代码(DFS ):
#include <bits/stdc++.h>

using namespace std;

// find k smallest element algorithm: DFS
// T(m, n) = O(log(m + n))
class Solution {
private:
// g++ -std=c++14 4.cpp -o 4.exe could compile successfully
// double findKSmall(auto s1, auto s2, int n1, int n2, int k){...}

typedef vector<int>	::iterator Iter;

double findKSmall(Iter s1, Iter s2, int n1, int n2, int k){
// Exceptional Case:
if(n1 > n2){
return findKSmall(s2, s1, n2, n1, k);
}
if(n1 == 0){
return *(s2 + k - 1);
}
if(k == 1){
return min(*s1, *s2);
}
int t1 = min(k / 2, n1);
int t2 = k - t1;
// delete t1 or t2 elements
double ans = -1.0;
if(*(s1 + t1 - 1) < *(s2 + t2 - 1)){
ans = findKSmall(s1 + t1, s2, n1 - t1, n2, k - t1);
}
else if(*(s1 + t1 - 1) > *(s2 + t2 - 1)){
ans = findKSmall(s1, s2 + t2, n1, n2 - t2, k - t2);
}
else{
ans = *(s1 + t1 - 1);
}
return ans;
}

public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n1 = nums1.size(), n2 = nums2.size();
auto s1 = nums1.begin(), s2 = nums2.begin();
double ans = -1.0;
// odd
if((n1 + n2) & 1){
ans = findKSmall(s1, s2, n1, n2, (n1 + n2) / 2 + 1);
}
// even
else{
ans = (findKSmall(s1, s2, n1, n2, (n1 + n2) / 2) + findKSmall(s1, s2, n1, n2, (n1 + n2) / 2 + 1)) / 2.0;
}
return ans;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C binary_search DFS
相关文章推荐