[アルゴリズムトピックのブレークスルー] 二分探索 - ソートされた配列内の要素の最初と最後の位置を見つける (17)

目次

1. 質問分析

2. アルゴリズム原理

3. コードの書き方

最後に次のように書きます。


1. 質問分析

質問リンク: 34. ソートされた配列内の要素の最初と最後の位置を見つける - LeetCode

この問題は、配列内のターゲット値の開始位置と終了位置を見つけることです。

2. アルゴリズム原理

ここで標準二等分を直接使用する場合、配列全体が同じ数値である場合、

O(N) に縮退してしまうので、ここで最適化する必要があります。

1.左端点を見つけることによって分析を開始します。x を中間値、t をターゲット値とします。

x < t の場合、左 = 中央 + 1

x >= t の場合、right = Mid (ここでは、以上の状況と等しい状況を組み合わせます)

この設定は、左 == 右の場合の最終結果です。

中点を見つける方法は、左 + (右 - 左) / 2 (つまり、偶数を見つける形式) でなければなりません。

このようにして、各ステップは左のエンドポイントに近くなり、無限ループに陥ることはありません。

2. 分析して適切なエンドポイントを見つけてみましょう:

x <= t の場合、left = Mid (ここで + 1 を使用しないのはなぜでしょうか。たまたまターゲット値に達した場合、すぐに超えてしまうからです。)

x > t の場合、right = Mid - 1

このように、左 == 右の場合、それが最終結果になります。

そして、中点を見つける方法は、 left + (right - left + 1) / 2 です。

こうすることで、各ステップが正しいエンドポイントに近づき、無限ループに陥ることがなくなります。

3. コードの書き方

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.size() == 0) return {-1, -1}; // 处理越界
        int left = 0, right = nums.size() - 1, begin = 0;
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(nums[mid] < target) left = mid + 1;
            else right = mid;
        }
        
        if(nums[left] != target) return {-1, -1};
        else begin = left;

        left = 0, right = nums.size() - 1;
        while(left < right) {
            int mid = left + (right - left + 1) / 2;
            if(nums[mid] <= target) left = mid;
            else right = mid - 1;
        }
        return {begin, right};
    }
};

4. 2 部構成のテンプレート

左側のエンドポイントを探す場合:

        while(左 < 右) {

            int ミッド = 左 + (右 - 左) / 2;

            if(...) 左 = 中央 + 1;

            それ以外の場合は右 = 中央;

        }

while (left < right) {

	int mid = left + (right - left) / 2;

	if (...) left = mid + 1;

	else right = mid;

}

適切なエンドポイントを探す場合:

        while(左 < 右) {

            int ミッド = 左 + (右 - 左 + 1) / 2;

            if(...) 左 = 中央;

            それ以外の場合は右 = 中央 - 1;

        }

while (left < right) {

	int mid = left + (right - left + 1) / 2;

	if (...) left = mid;

	else right = mid - 1;

}

最後に次のように書きます。

以上がこの記事の内容です、読んでいただきありがとうございます。

何かを得たと感じたら、ブロガーに「いいね! 」を与えることができます。

記事の内容に漏れや間違いがある場合は、ブロガーにプライベートメッセージを送信するか、コメント欄で指摘してください〜

おすすめ

転載: blog.csdn.net/Locky136/article/details/131804239