leetcode——Median of Two Sorted Array

原題爲:算法

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)).數組

好吧,我是普通青年,第一反應就是使用Merge兩個數字的思想,直接找到中位數。可是這個算法的複雜度是O(m+n)。ide

leetcode給這道題打上的標籤是divide and conquer以及binary search。其實我以爲這個標籤有點誤導性。百思不得其解以後看了關於這道題的discussion,看完以後不由感嘆:我數學沒學好。編碼

這道題的解題思路是這樣子的:code

該方法的核心是將原問題轉變成一個尋找第k小數的問題(假設兩個原序列升序排列),這樣中位數其實是第(m+n)/2小的數。因此只要解決了第k小數的問題,原問題也得以解決。遞歸

首先假設數組A和B的元素個數都大於k/2,咱們比較A[k/2-1]和B[k/2-1]兩個元素,這兩個元素分別表示A的第k/2小的元素和B的第k/2小的元素。這兩個元素比較共有三種狀況:>、<和=。若是A[k/2-1]<B[k/2-1],這表示A[0]到A[k/2-1]的元素都在A和B合併以後的前k小的元素中。換句話說,A[k/2-1]不可能大於兩數組合並以後的第k小值,因此咱們能夠將其拋棄。而後在兩個數組剩下的元素裏尋找第k-(k/2)大的元素(經過遞歸的方式)。leetcode

當A[k/2-1]>B[k/2-1]時存在相似的結論。數學

當A[k/2-1]=B[k/2-1]時,咱們已經找到了第k小的數,也即這個相等的元素,咱們將其記爲m。因爲在A和B中分別有k/2-1個元素小於m,因此m便是第k小的數。(這裏可能有人會有疑問,若是k爲奇數,則m不是中位數。這裏是進行了理想化考慮,在實際代碼中略有不一樣,是先求k/2,而後利用k-k/2得到另外一個數。)it

如何證實以上的規律是數學書裏的內容,這裏不作太多介紹。io

在實際的編碼過程當中,咱們須要考慮以下邊界條件:

    1. 若是m或者n爲0,直接返回A[k-1]或者B[k-1];

    2. 若是k爲1,那麼返回A[0]或者B[0]當中較小的一個;

    3. 若是A[k/2-1] == B[k/2-1],那麼直接返回兩個數中的任何一個。

代碼以下:

class Solution 
{
public:
	double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) 
	{
		int m = nums1.size();
		int n = nums2.size();
		//cout << m << " " << n << endl;
		if ((m+n)%2 == 0)
		{
			//cout << "even" << endl;
			return (findKthNum(nums1, nums2, (m + n) / 2) + findKthNum(nums1, nums2, (m + n) / 2 + 1))/2;
		}
		else
		{
			//cout << "odd" << endl;
			return findKthNum(nums1, nums2, (m + n) / 2 + 1);
		}
	}

	int min(int a, int b)
	{
		if (a < b)
		{
			return a;
		}
		else
		{
			return b;
		}
	}

	double findKthNum(vector<int>& nums1, vector<int>& nums2, int k)
	{
	    if (nums1.size() > nums2.size())
		{
			return findKthNum(nums2, nums1, k);  //注意nums1的size必定要比nums2小,否則會發生溢出錯誤
		}
		//當m或者n爲0時
		if (nums1.size() == 0)
		{
			if (k <= nums2.size())
			{
				return nums2[k - 1];
			}
			else
			{
				return nums2[nums2.size() - 1];
			}
		}
		else if (nums2.size() == 0)
		{
			if (k <= nums1.size())
			{
				return nums1[k - 1];
			}
			else
			{
				return nums1[nums1.size() - 1];
			}
		}
		if (k == 1)
		{
			return min(nums1[0], nums2[0]);
		}
		int offset_1 = min(k / 2, nums1.size());
		int offset_2 = k - offset_1;
		vector<int> new_nums1, new_nums2;
		int i = 0;
		if (nums1[offset_1-1] == nums2[offset_2-1])
		{
			return nums1[offset_1-1];
		}
		else if (nums1[offset_1-1] < nums2[offset_2-1])
		{
			for (vector<int>::iterator it = nums1.begin(); it != nums1.end(); it++)
			{
				if (i >= offset_1)
				{
					new_nums1.push_back(*it);
				}
				i++;
			}
			return findKthNum(new_nums1, nums2, k - offset_1);
		}
		else
		{
			for (vector<int>::iterator it = nums2.begin(); it != nums2.end(); it++)
			{
				if (i >= offset_2)
				{
					new_nums2.push_back(*it);
				}
				i++;
			}
			return findKthNum(nums1, new_nums2, k - offset_2);
		}
	}
};
相關文章
相關標籤/搜索