[質問バンクをスワイプ]二分探索アルゴリズムのアイデアとテンプレート

序文

長さ1000メートルのパイプがあり、未知の場所に穴があるとします。この穴を見つけたい場合、どのように探す必要がありますか?

実際のアプリケーションでは、価格の高い順に排出する、対象物の大きさに応じた連続排出、上記のパイプライン検査などの問題など、さまざまな場所で順次排出のシーケンスを見ることができます。

条件を満たす特定の値を見つける必要がある場合、順番に検索するために多くの不要な検索が必要になります。現時点では、2つのポイントを使用することで多くのコストを節約できます。

上記の1000メートルのパイプラインに直面して、二分メカニズムを採用することができ、毎回、次の検索のためにできるだけ多くのパイプライン除外します。ここに画像の説明を挿入

二分探索

テンプレート検索プロセスをよりよく理解するために、最初に簡単な例を挙げましょう

順序付きリストで、要素54を見つけます
ここに画像の説明を挿入

最初のラウンド

l = 0
r = 13
mid = (l + r) / 2 = 6

現時点では、midが指す数は54未満であるため、54はmidとrの間にあり、lからmidまでのすべてのデータを除外できます。
ここに画像の説明を挿入

第2ラウンド

l = mid + 1 = 7
r = 13(不变)
mid = (l + r) / 2 = 10

このとき、midが指す数は54より大きいので、54はlとmidの間にあり、midからrまでのすべてのデータを除外できます。

ここに画像の説明を挿入

第3ラウンド

l =  7(不变)
r = mid = 10
mid = (l + r) / 2 = 8

このとき、midが指す数は54で、検索は終了します。

ここに画像の説明を挿入

時間計算量:O(logN)

スペースの複雑さ:O(1)

ここでの複雑さは実際には平均の複雑さです。アルゴリズムのログレベルの時間計算量は分割統治の概念を使用しています。このベースは分割統治の複雑さによって決定されます。つまり、バイナリ検索メカニズムが使用されます。その場合、そのベースは2です。

テンプレート1

ある上司のテンプレートを参考に、学習しやすいように説明しました

間隔[l, r]がに分割され[l, mid][mid + 1, r]その更新操作中にがr = midまたはl = mid + 1;の場合、計算された中間に1を追加する必要はありません。

コードテンプレート

function search_1(l, r)
{
    
    
    while (l < r)
    {
    
    
        var mid = l + r >> 1;
        if(/*mid找到*/) return mid;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return false;
}

ここに画像の説明を挿入

  1. なぜl < rそれを終わらせる条件なのですか?

    回答:上の写真によると、ターゲットが見つからない場合は、左右のポインターが重なり、重なり合うと終了します。

  2. なぜそれを使用l + r >> 1するのですか、他の方法はありますか?

    解決策:JavaScriptでは、10進整数を削除する方法parseInt()Math.floor()>>変位可能な方法が採用されているため、右の矢印は1を示しているように見えます。つまり、2で割ってから丸められMath.floor((l + r) / 2)ますが、今回は同じ効果があります。

テンプレート2

間隔[l, r]がに分割され[l, mid - 1][mid, r]その更新操作中にがr = mid - 1またはである場合l = mid、この時点で無限ループを防ぐために、コンピューティングmidは1を追加する必要があります。

function search_2(l, r)
{
    
    
    while (l < r)
    {
    
    
        var mid = l + r + 1 >> 1;
        if(/*mid找到*/) return mid;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return false;
}

使用する

上記の配列でも、テンプレート1を使用して54を検索します

var array = [1, 2, 4, 9, 11, 15, 20, 25, 54, 90, 100, 110, 111, 242];
function search_1(nums, target) {
    
    
    if (target == null || nums.length == 0) return false;

    var l = 0,
        r = nums.length - 1;
    while (l < r) {
    
    
        var mid = (l + r) >> 1;
        if(target == nums[mid]) return mid;
        if (target < nums[mid]) {
    
    
            r = mid;
        } else {
    
    
            l = mid + 1;
        }
    }
    return false;
}
function search_2(nums, target) {
    
    
    if (target == null || nums.length == 0) return false;

    var l = 0,
        r = nums.length - 1;
    while (l < r) {
    
    
        var mid = (l + r + 1) >> 1;
        if(target == nums[mid]) return mid;
        if(target > nums[mid]) l = mid;
        else r = mid - 1;
    }
    return false;
}

総括する

二分探索では、データが正常である必要があります。

  1. 中央の位置がターゲットと比較され、等しいかどうかが検出されます。それ以外の場合は、元のテーブルを2つのテーブルに分割します
  2. l > r時間が見つからないとき

おすすめ

転載: blog.csdn.net/weixin_42339197/article/details/103911189