1. 程式人生 > >Median of Two Sorted Arrays 求出兩個已排序陣列的中位數

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

大意就是求出兩個已排序陣列的中位數.  如果總共有偶數個元素, 返回兩個中間數的和的一半. 所以返回型別是double

還要求時間複雜度為O(log (m+n)).

初看這題,馬上想到的就是使用 merge sort,將兩個數組合並起來後直接返回中間數, 這樣非常省力.但時間複雜度平均下倆就是O(m+n)

了, 而不是要求的O(log (m+n)).

如下所示:

double findMedianSortedArrays(int A[], int m, int B[], int n) {
		int i = 0, j = 0, k = 0;
		int *C = new int[m+n];
		while (i < m && j < n)
		{
			if (A[i] < B[j])
				C[k++] = A[i++];
			else
				C[k++] = B[j++];
		}

		while (i < m)
			C[k++] = A[i++];

		while (j < n)
			C[k++] = B[j++];

		int mid = (m + n) / 2;
		if ((m + n) % 2 == 0)
			return (double)(C[mid] + C[mid - 1]) / 2;
		else
			return C[mid];
	}

既然無法達到要求, 那麼只能換一種思路. 根據題目給出的時間複雜度, 我們一般會想到的排序方法有merge sort, quick sort等

對於查詢的演算法, 比如二分查詢,  或是利用二叉樹的變形來查詢, 雜湊查詢顯然更快, 但明顯不適合這裡.

所以, 最終選擇了二分查詢.

下面是參考了別人的程式碼:

#include <stdio.h>

//這個二分查詢, 找到目標value就會返回其下標; 如果沒有找到, 會返回它應該插入的位置
int BinarySearch(int *nums, int start, int end, int value){
	int mid; 
	while(start <= end){
		mid = start + (end - start) / 2;
		if(nums[mid] >= value)
			end = mid - 1;
		else
			start = mid + 1;
	}

	return start;
}

//以下部分引數為二分查詢所需
double recusiveFindMedian(int *A, int m, int *B, int n, int A_Start, int A_End, int B_Start, int B_End){
	//A_Mid表示A陣列中間數的下標, 也表示在A陣列中, 該數之前有多少個數字
	int A_Mid = A_Start + (A_End - A_Start) / 2;
	//找到A陣列的中間數在B中的位置. 也表示在B陣列中, 該數之前有多少個數字
	int A_Mid_Pos_In_B = BinarySearch(B, B_Start, B_End, A[A_Mid]);
	//最終就得到了合併後, 該數之前會有多少個數存在
	int A_Mid_Final = A_Mid + A_Mid_Pos_In_B;

	//如果這個數在最終合併的陣列中仍然處於中間位置
	//那麼就繼續考慮合併後的陣列的元素個數是偶數還是奇數.
	//如果合併後有奇數個數字, 直接返回這個數;
	//如果合併後有偶數個數字, 那麼返回這個數和這個數之前的數的和的一半
	if(A_Mid_Final == (m + n)/2){
		//比如陣列A:[1, 3, 5]; 陣列B:[2, 4]; 那麼
		//	A_Mid = 1; A_Mid_Pos_In_B = 1; A_Mid_Final = 2 == (m + n) / 2; 直接返回就可以
		//比如陣列A:[3, 5]; 陣列B:[1, 2, 4]; 那麼
		//	A_Mid = 0; A_Mid_Pos_In_B = 2; A_Mid_Final = 2 == (m + n) / 2; 依舊直接返回
		//比如陣列A:[5, 9]; 陣列B:[2, 4]; 那麼
		//	A_Mid = 0; A_Mid_Pos_In_B = 2; A_Mid_Final = 2 == (m + n) / 2;
		//	因為是偶數個元素, 所以最終返回 (A[0] +B [1])/2 = 4.5
		if((m + n) & 1)
			return A[A_Mid];

		int prev;
		//既然 A_Mid 等於偶數的一半, 比如(2+4)/2 = 3; 那麼最終的返回值應該是合併後的(M[3]+M[2])/2才對
		//因為 0,1,2,3,4,5 中間兩個數是2和3
		//但是如果出現 (1 + 3)/2 = 2的情況,比如
		//	[2, 3, 4]; [5]; 此時A_Mid_Pos_In_B = 0, 這時候只能返回 (A[1]+A[2])/2
		//又或者這種情況:
		//	[3]; [2, 4 ,5]; 此時就要 (A[0] + B[1])/2
		//又或者兩陣列都只有1個元素, 這樣只要返回兩數和的一半就行了
		//其他普通情況就是從A陣列或B陣列中挑一個小於A_Mid又離的最近的就行了
		if(A_Mid > 0 && A_Mid_Pos_In_B > 0)
			prev = A[A_Mid-1] > B[A_Mid_Pos_In_B-1] ? A[A_Mid-1] : B[A_Mid_Pos_In_B-1];
		else if(A_Mid > 0)
			prev = A[A_Mid - 1];
		else if(A_Mid_Pos_In_B > 0)
			prev = B[A_Mid_Pos_In_B - 1];
		else
			prev = B[A_Mid_Pos_In_B];

		return (A[A_Mid] + prev) / 2.0 ;
	}
	else if(A_Mid_Final < (m + n)/2){
		//既然這個數在合併後的陣列中的位置是在左半邊的, 那麼我們就要用比這個數大的數來繼續尋找
		//就是二分查詢的概念, 現在往右邊找
		//在A陣列中, A_Mid肯定不符合要求了, 所以加一往後找
		//在B陣列中, A_Mid_Pos_In_B可能與A_Mid的值相同, 也可能是A_Mid對應的值應該要插入的位置, 所以不能加一
		A_Start = A_Mid + 1;
		B_Start = A_Mid_Pos_In_B;
		if((A_End - A_Start) > (B_End - B_Start))
			return recusiveFindMedian(A, m, B, n, A_Start, A_End, B_Start, B_End);
		return recusiveFindMedian(B, n, A, m, B_Start, B_End, A_Start, A_End);
	}
	else{
		//這裡能減1是有多個條件促成的
		//	A陣列是較長的陣列
		//	A陣列中的中間數在合併後的陣列的右邊
		A_End = A_Mid - 1;
		//B陣列能捨棄一些元素是因為, 兩個陣列是sorted的
		//這裡能減1也是因為A_Mid_Pos_In_B可能與A_Mid的值相同, 也可能是A_Mid對應的值應該要插入的位置
		B_End = A_Mid_Pos_In_B - 1;	
		if((A_End - A_Start) > (B_End - B_Start))
			return recusiveFindMedian(A, m, B, n, A_Start, A_End, B_Start, B_End);
		return recusiveFindMedian(B, n, A, m, B_Start, B_End, A_Start, A_End);
	}
}

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
	if(nums1Size == 0 && nums2Size == 0)
		return 0.0;
	
	if(nums1Size == 0)
		return (nums2Size%2==1 ? nums2[nums2Size/2] : (nums2[nums2Size/2-1] + nums2[nums2Size/2])/2.0);

	if(nums2Size == 0)
		return (nums1Size%2==1 ? nums1[nums1Size/2] : (nums1[nums1Size/2-1] + nums1[nums1Size/2])/2.0);
	
	//下面我們保證recusiveFindMedian中A的陣列長度一定是不小於B的
	if(nums1Size > nums2Size)
		return recusiveFindMedian(nums1, nums1Size, nums2, nums2Size, 0, nums1Size-1, 0, nums2Size-1);
	
	return recusiveFindMedian(nums2, nums2Size, nums1, nums1Size, 0, nums2Size-1, 0, nums1Size-1);
}

int main()
{
	int ar1[] = {1, 12, 15, 26, 38};
	int ar2[] = {2, 13, 17, 30, 45, 50};
	printf("Median is 17 = %f\n", findMedianSortedArrays(ar1, 5, ar2, 6));
	return 0;
}
總體的思想是利用較長陣列的中間數在合併後陣列中的位置來進行的二分查詢.

這又讓人想起了快速排序中的Partition演算法...

相關推薦

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

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

用O(lgn)時間排序陣列位數

相關問題: 設 x[1..n]和Y[1..n]為兩個陣列,每個都包含n個已排序的數。給出一個求陣列X和Y中所有2n個元素的中位數的O(lgn)時間的演算法。 思考過程:         開始我想把兩個陣列X與Y放入到一個數組Z中,對Z進行排序,這樣Z的中位數易求。但是有2點

LeetCode 4. Median of Two Sorted Arrays (有序陣列第k大數字,分治法)

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 complex

LeetCode 21 Merge Two Sorted Lists(合併排序的連結串列)(Linked List)

翻譯 合併兩個排好序的連結串列,並返回這個新連結串列。 新連結串列應該由這兩個連結串列的頭部拼接而成。 原文 Merge two sorted linked lists and return it as a new list. The new

有序數組的位數(4. Median of Two Sorted Arrays

排序 font float 序列 大小 width 技術 display 個數 先吐槽一下,我好氣啊,想了很久硬是沒有做出來,題目要求的時間復雜度為O(log(m+n)),我猜到了要用二分法,但是沒有想到點子上去。然後上網搜了一下答案,感覺好有罪惡感。 題目原型 正確的

【死磕演算法之1刷Leetcode】——找有序陣列位數Median of Two Sorted Arrays】O(log(m+n))

Median of Two Sorted Arrays 題目難度:hard 題目要求: There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two s

[LeetCode]Median of Two Sorted Arrays 二分查找有序數組的第k數(位數

大於 data div ble 關系 操作 spa 兩個 -1 二分。情況討論 因為數組有序,所以能夠考慮用二分。通過二分剔除掉肯定不是第k位數的區間。如果數組A和B當前處理的下標各自是mid1和mid2。則 1、假設A[mid1]<B[mid2], ①

[LeetCode] 4. Median of Two Sorted Arrays 有序數組的位數

數據 pub art cti AI nts highlight sta binary There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of t

【LeetCode】4.Median of Two Sorted Arrays 排序陣列位數

示例 1: nums1 = [1, 3] nums2 = [2] 中位數是 2.0 示例 2: nums1 = [1, 2] nums2 = [3, 4] 中位數是 (2 + 3)/2 = 2.5 解題思路: 糟糕- -沒理解題意,首先需要知道“中位數”

leetcode 排序陣列位數Median of Two Sorted Arrays

解決方案 方法:遞迴法 為了解決這個問題,我們需要理解“中位數的作用是什麼”。在統計中,中位數被用來: 將一個集合劃分為兩個長度相等的子集,其中一個子集中的元素總是大於另一個子集中的元素。 如果理解了中位數的劃分作用,我們就很接近答案了。 首先,讓我們在任一位置

[LeetCode] 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 shou

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 overa

Leetcode 4. Median of Two Sorted Arrays 尋找有序陣列位數

Leetcode 4. Median of Two Sorted Arrays 尋找兩個有序陣列的中位數 標籤: Leetcode 題目地址:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ 題目

4.、Median of Two Sorted Arrays(有序序列的位數)

題目要求在給定兩個長度分別為m和n的有序序列時,找出這兩個序列合起後的中位數。並且要求時間複雜度為O(log(m+n))。首先,中位數的定義是,當序列長度為偶數時,中位數的值為序列中間兩個數的均值;當序列為奇數時,中位數為正中間的數。當序列長度為n時,其值分別為(array[

LeetCode(40) 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

有序陣列位數Median of Two Sorted Arrays(很重要)

https://leetcode.com/problems/median-of-two-sorted-arrays/ 對於一個長度為n的已排序數列a,若n為奇數,中位數為a[n / 2 + 1]

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 ru

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 tim

有序陣列位數 Median of Two Sorted Arrays

Leetcode上的一道題: There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall ru