。巧妙な使用の二分法 - Leetcode4は2の秩序配列の中央値を見つけます

記事のディレクトリ

導入

この質問はこれです:

4.中央値2は、配列命じ検索
サイズとnums1 m、nはnums2の2つの命じた配列を考えると。
メジアンおよび整然とした配列の両方を検索し、アルゴリズムの時間複雑度はO(ログ(M + n)が必要としてください )。
あなたはnums1とnums2を想定し、両方の空にすることはできません。
実施例1:
nums1 = [1、3]
nums2 = [2]
中央値が2.0である
実施例2:
nums1 = [1、2]
nums2 = [3 ,. 4]は
、中央値は(2 + 3)/ 2 = 2.5

その方法を持つ人々の半分が要件を満たすことができるようにして、O(LOGN)のアルゴリズムの時間計算を使用する必要があります。

中央の秩序配列を探し、他の言葉で、それは、最小の数の半分に配列の長さを見つけることです。たとえば、次のように[1,2,2、2、3,4,5]は、検索に対応し、アレイの中央値を見つけるために、(7 + 1)/ 2 =番号3。言い換えれば、それは、アレイの半分を見つけることです、このような偶数の配列、[1,2,2の場合も考えてみましょう23、3,4,5〕、配列の長さは、(8 + 1)の半分/ 2 = 4、(8 + 2)/ 2 = 5であり、8です。

そこで、我々は見つけるための方法を見つける必要がある2出てくる準備ができて半分ソート配列、メソッドの意志を。

Leetcodeの問題解決

nは、それぞれ、K上のビット数が想定されている二つの長さmの配列とは、言うことである、我々は、(m及びnに応じてk番目に小さい数またはK及びK + 1、数時間のための2つを見つける必要がありますパリティ)。

私たちは、あるk番目の最小数を、導くことができます。 K 1 = メートル + n個 + 1 / 2 K_1 =(M + N + 1)/ 2 K 2 = メートル + n個 + 2 / 2 K_2 =(M + N + 2)/ 2

:我々は、k番目の最小数を見つけるために以下の方法を使用することができ、それはK = 7と仮定すると仮定することができる
ここに画像を挿入説明
、我々は/ 2位置リストkの最初のを見つけることができます。次いで、比較nums1 [K / 2]とサイズnums2 [K / 2]、及びアレイの小さいK / 2、すなわち地図上に、それが中央値ではないので、必ずしも2 / K、除外することができる前1,2,3中央値ではありません。

私たちは考える、これはそれを除外することができますか
アレイの比率/ 2-1ヶ月A [K / 2]小数値kを有するが、配列Bで、B [K / 2] Aの比は[K / 2]の前にデジタルB [K / 2]を仮定し、小さいです[K / 2]は小さい場合よりも、唯一のK / 2-1ヶ月、アップ/ 1-1 + K / 2-1 = kに[K / 2]少数の比 K-2 2、そう[K / 2]はK-1で最も小さい数です。それらは排除することができるので、A [K / 2]の比は、K少数の小さな数である可能性が低いです。

この考え方によれば、第2の除外が、今回、彼らはK / 2のGeを除外しているので、これだけ(KK / 2)を除外しなければならない/ 2評価:
ここに画像を挿入説明
つまり、これは2つだけを除外。

したがって、このように、次はK = 2、K / 2 = 1の場合であり、kの始まりは7に等しいので、この時点では、直接、答えを得ることができない、唯一のこの時間は、我々はまだ排除する必要がある、5を除外しに行きますA。この時間は、以下の4を除外していると仮定することができる、続行。
ここに画像を挿入説明

この時点での状況は次のとおりです。
ここに画像を挿入説明
中央値が存在しなければならない、の中で、この時点数2で、と言うことです、K = 1、、我々が最初のk個の小型のためにされて見ていることは明らかであるその数、そしてマップ我々は4で探しています。

次のようにさて、この質問のコードは次のとおりです。

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    int n = nums1.length;
    int m = nums2.length;
    int left = (n + m + 1) / 2;
    int right = (n + m + 2) / 2;
    //将偶数和奇数的情况合并,如果是奇数,会求两次同样的 k 。
    return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5;  
}
    
    private int getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) {
        int len1 = end1 - start1 + 1;
        int len2 = end2 - start2 + 1;
        //让 len1 的长度小于 len2,这样就能保证如果有数组空了,一定是 len1 
        if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);
        if (len1 == 0) return nums2[start2 + k - 1];

        if (k == 1) return Math.min(nums1[start1], nums2[start2]);

        int i = start1 + Math.min(len1, k / 2) - 1;
        int j = start2 + Math.min(len2, k / 2) - 1;

        if (nums1[i] > nums2[j]) {
            return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
        }
        else {
            return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
        }
    }

あとがき
この二分法のタイトルには追加、などまだ非常に多く使用さ質問、の二分法:
69 xの平方根

公開された385元の記事 ウォンの賞賛326 ビュー160 000 +

おすすめ

転載: blog.csdn.net/No_Game_No_Life_/article/details/103999858