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

题目描述:

    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;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值