国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

Median of Two Sorted Arrays(求兩個數(shù)組的中位數(shù))

2019-11-06 06:21:00
字體:
供稿:網(wǎng)友

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

Example 1:

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

The median is 2.0

Example 2:

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

The median is (2 + 3)/2 = 2.5

原題:https://leetcode.com/PRoblems/median-of-two-sorted-arrays/?tab=Description

分析:通常情況下我們要求得一系列數(shù)中的中位數(shù),應(yīng)該都是要知道所有的數(shù)之后才能決定中位數(shù)的具體值,也就是具有O(n)以上的復(fù)雜度。但是,假如說知道了給定的一系列數(shù)的大小關(guān)系(即已經(jīng)有序排列好),則我們可以直接根據(jù)這一系列數(shù)的個數(shù)直接判斷。比如總個數(shù)為n,當(dāng)n為奇數(shù)時,中位數(shù)應(yīng)該在n / 2處;當(dāng)n為偶數(shù)時,中位數(shù)應(yīng)該為n / 2 - 1與n / 2的平均值。此處數(shù)列的取值范圍是[ 0, n )。 上題中給定的條件是兩個已有序的數(shù)組(題意應(yīng)該是默認從小到大排列)。最簡單直接的方法是通過一個merge過程將兩列數(shù)合并為一列數(shù),再用上述的O(1)的方法直接得到結(jié)果,這樣總過程是O(n)的復(fù)雜度。但是題目要求的是O(log(m+n))的復(fù)雜度。 不妨設(shè)兩組數(shù)為A[n]、B[m],且n <= m。解決方法是始終取定一組數(shù),個數(shù)為k = (n + m - 1) / 2 + 2 。這樣,在這一組數(shù)中一定包含了中位數(shù)或者取得中位數(shù)的必要信息,且都是在這k個數(shù)的“邊緣”取得。假如這k個數(shù)取A[]、B[]中較小的一部分,則“邊緣數(shù)”為k個數(shù)范圍內(nèi)最大的第一個、第二個和第三個。一般情況下,這k個數(shù)必須在A[]、B[]中同時取得,設(shè)在A[]中最大的數(shù)為A[midA]、在B[]中最大的數(shù)為B[midB]。 以下是一種經(jīng)檢驗證明可行的算法:

public double findMedianSortedArrays(int A[], int B[]) { int n = A.length; int m = B.length; // the following call is to make sure len(A) <= len(B). // yes, it calls itself, but at most once, shouldn't be // consider a recursive solution if (n > m) return findMedianSortedArrays(B, A); // now, do binary search int k = (n + m - 1) / 2; int l = 0, r = Math.min(k, n); // r is n, NOT n-1, this is important!! while (l < r) { int midA = (l + r) / 2; int midB = k - midA; if (A[midA] < B[midB]) l = midA + 1; else r = midA; } // after binary search, we almost get the median because it must be between // these 4 numbers: A[l-1], A[l], B[k-l], and B[k-l+1] // if (n+m) is odd, the median is the larger one between A[l-1] and B[k-l]. // and there are some corner cases we need to take care of. int a = Math.max(l > 0 ? A[l - 1] : Integer.MIN_VALUE, k - l >= 0 ? B[k - l] : Integer.MIN_VALUE); if (((n + m) & 1) == 1) return (double) a; // if (n+m) is even, the median can be calculated by // median = (max(A[l-1], B[k-l]) + min(A[l], B[k-l+1]) / 2.0 // also, there are some corner cases to take care of. int b = Math.min(l < n ? A[l] : Integer.MAX_VALUE, k - l + 1 < m ? B[k - l + 1] : Integer.MAX_VALUE); return (a + b) / 2.0;}

注:該算法引用自:https://leetcode.com/problems/median-of-two-sorted-arrays/?tab=Solutions ( 4.Share my iterative solution) with O(log(min(n, m)))

>

算法是這樣執(zhí)行的:1、初始化: 在A中取定[left, right), 作為midA的取值范圍,其中l(wèi)eft = 0; right = min(k, n),從而保證midA的取值有意義。而midB = k - midA,從而保證midA + midB = k。2、迭代步驟: 保持left < right,從而確保midA = (left + right) / 2的取值有意義。如果A[midA] < B[midB],則向上提升midA的值,方法是令left = midA + 1,并進行下一步迭代;如果A[midA] <= B[midB],則向下降低midA的值,方法是令right = midA,并進行下一步迭代。這樣做使得A[midA],B[midB]這些k個數(shù)中的“邊緣”值越來越接近中位數(shù)的要求。因為如果A[midA] < B[midB],向上提升midA的值意味著A[midA]增大,且midB的值下降,從而B[midB]減小,從而A[midA] < B[midB]可能不再成立,結(jié)果可能是A[midA] >= B[midB]。如此,使得A[midA]、B[midB]越來越逼近于某個中間值,從而最終穩(wěn)定在中位數(shù)附近并退出迭代過程。3、得出中位數(shù): 經(jīng)過2的迭代步驟,A[midA]、B[midB]已經(jīng)接近目標(biāo)中位數(shù)了,剩下的是一些邊緣條件的處理。要注意的是該算法中數(shù)的取值范圍是A[0, n),B[0,m)。可以判斷步驟2中迭代的終止條件必然是right == left。此時分兩種情況,第一種:由right降至left,即A[left] >= B[k - left],從而right = midA,從而right == left;第二種:由left升至right,此時又分兩種情況,即left == right - 1 和left == right - 2 兩種情況,但是兩種情況綜合之后,以right == left時的left為準,必有A[left - 1] < B[k - left + 1]。綜合上述情況,可以基本判斷與中位數(shù)有關(guān)的“邊緣”數(shù)有四個:A[left]、A[left - 1]、B[k - left]、B[k - left + 1]。該算法的最后一步便是根據(jù)具體情況綜合這四個數(shù)得到答案了。

以下是我根據(jù)算法偽代碼寫的C++代碼,基本上與偽代碼差不多。

#include <climits>using namespace std;class Solution {public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { if (nums1.size() == 0) { if (nums2.size() % 2 == 0) { return double(nums2[nums2.size() / 2 - 1] + nums2[nums2.size() / 2]) / 2.0; } else { return double(nums2[nums2.size() / 2]); } } else if (nums2.size() == 0) { if (nums1.size() % 2 == 0) { return double(nums1[nums1.size() / 2 - 1] + nums1[nums1.size() / 2]) / 2.0; } else { return double(nums1[nums1.size() / 2]); } } int n = nums1.size(), m = nums2.size(); if (n > m) return findMedianSortedArrays(nums2, nums1); int k = (n + m - 1) / 2; int l = 0, r = min(k, n); while (l < r) { int midA = (l + r) / 2; int midB = k - midA; if (nums1[midA] < nums2[midB]) l = midA + 1; else r = midA; } int a = max(l > 0 ? nums1[l - 1] : INT_MIN, k - l >= 0 ? nums2[k - l] : INT_MIN); if ((n + m) % 2 == 1) { return double(a); } else { int b = min(l < n ? nums1[l] : INT_MAX, k - l + 1 < m ? nums2[k - l + 1] : INT_MAX); return double(a + b) / 2.0; } } int max(int a, int b) { if (a > b) return a; else return b; } int min(int a, int b) { if (a < b) return a; else return b; }};
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 米易县| 金昌市| 昌都县| 阜康市| 册亨县| 依安县| 新源县| 平乡县| 山东| 福鼎市| 广宁县| 博湖县| 井陉县| 尉氏县| 贺州市| 东安县| 红安县| 大宁县| 西平县| 上饶市| 星座| 延津县| 汨罗市| 秭归县| 峨山| 桂东县| 安化县| 莱西市| 安宁市| 霸州市| 东台市| 松溪县| 瑞金市| 安庆市| 绥棱县| 博客| 曲周县| 项城市| 富源县| 晋州市| 黎川县|