4. 兩個排序陣列的中位數

關關的刷題日記發表於2018-04-06

有兩個大小為 m 和 n 的排序陣列 nums1 和 nums2 

請找出兩個排序陣列的中位數並且總的執行時間複雜度為 O(log (m+n)) 。

示例 1:

nums1 = [1, 3]
nums2 = [2]

中位數是 2.0

 

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

中位數是 (2 + 3)/2 = 2.5

下面這個連結講得很好了。

https://leetcode.com/problems/median-of-two-sorted-arrays/discuss/2481/Share-my-O(log(min(m,n))-solution-with-explanation

著重介紹一下怎麼處理邊界:

1、需要滿足條件:B[j-1] <= A[i] and A[i-1] <= B[j]

2、某些邊界情況下,i=0/i=m/j=0/j=n,有些不存在了。這個時候只需要滿足存在的即可

3、所以需要滿足條件: (j == 0 or i == m or B[j-1] <= A[i]) and (i == 0 or j == n or A[i-1] <= B[j])

兩兩組合一共九種情況,排除掉一些不可能的情況,

(j == 0 or i == m or B[j-1] <= A[i]) and (i == 0 or j == n or A[i-1] <= B[j])

這個時候只剩下5中情況,程式碼中會有註釋。

i == 0 && B[j-1]<=A[i]

j == n && B[j-1]<=A[i]

j == 0 && A[i-1]<=B[j]

i == m && A[i-1]<=B[j] 

B[j-1] <= A[i] and A[i-1] <= B[j]

 

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

double find_median(vector<int>& A, vector<int>& B) {
    //初始化,處理邊界
	int m = A.size(), n = B.size(), p, q, l, r;
	if (A.empty() && B.empty()) return 0;
	if (A.empty()) return n % 2 == 1 ? B[n/2]: (B[n/2-1]+B[n/2])/2.0;
	if (B.empty()) return m % 2 == 1 ? A[m / 2] : (A[m / 2 - 1] + A[m / 2]) / 2.0;

    //選取較短的陣列s來做二分。	
    if (m > n)    
	{
		swap(A,B);
		m = B.size();
		n = A.size();
	}

	l = 0,r = m;
	while (l <= r)
	{
		p = l + (r - l) / 2;
		q = (m + n + 1) / 2 - p;
		if (p<m && (s[p] < ss[q - 1]))  //p右移
			l = p + 1;
		else if (p>0 && s[p - 1] > ss[q])//p左移
			r = p - 1;
		else   //找到p  
		{
			if (p == 0)    
			{
				if (m == n)
					return (s[p] + ss[q - 1]) / 2.0;
				else
					return (m + n) % 2 == 1 ? ss[q - 1] : (min(s[p], ss[q]) + ss[q - 1]) / 2.0;
			}			
			if (p == m)    
				return (m + n) % 2 == 1 ? max(s[p - 1], ss[q - 1]) : (max(s[p - 1], ss[q - 1]) + ss[q])/ 2.0;
			if (q == 0)    
				return (s[p - 1] + s[q]) / 2.0;
			if (q == n)    
				return (m + n) % 2 == 1 ? ss[q - 1] : (s[p] + ss[q - 1]) / 2.0;
			else          
				break;
		}
	}
	return  (m + n) % 2 == 1 ? max(s[p - 1], ss[q - 1]) : (max(s[p - 1], ss[q - 1]) + min(s[p], ss[q])) / 2.0;
}

int main()
{
	vector<int> A = {3};
	vector<int> B = { 1,2,4};
	vector<int> C = { 1 };
	vector<int> D = { 2, 3 };
	double re1 = 0, re2 = 0;
	re1 = find_median(A, B);
	//re2 = find_median(C, D);
	cout << "re1=" << re1 << endl;  //5.5
	//cout << "re2=" << re2 << endl; //5
	return 0;
}

 

相關文章