[Leetcode /バイナリ]最初と最後の位置にソートされた配列の要素を見つける(半鋳型3)

問題の説明:

昇順に配列された整数の配列を指定してnums、目標値targetアレイ内の所与の標的の開始および終了位置を特定します。

アルゴリズムのあなたの時間複雑でなければなりません  O(ログのN-)レベル。

何のターゲット配列とリターンが存在しない場合  [-1, -1]

例1:

入力: NUMS = [ 5,7,7,8,8,10]8 =ターゲット。
 出力: [3,4]

例2:

入力: NUMS = [ 5,7,7,8,8,10]6 =ターゲット。
 出力: [-1、-1]

基本的な考え方:

非常に単純な、見つけることである一番左のターゲットを、見つけることですターゲット右端のを

ここでは、二分思考の使用は、これはソート配列に1つの単純な要素を見つける前半分ではありません。

彼はこれに周囲の要素、に従ってランク付けする直接の要素は左と右の点を決定、我々は半ば要素の判断をあきらめるかもしれません

これは、要素を取り巻く環境で左右の点から、一定周期、私たちを介している互いの中にバンプする左右、その位置の結果です

(ただし、そこに問題があり、それはある左右の隣接する時間が無限ループを引き起こす可能性がある場合は

普通によると、半ば= +左(右-左 )/ 2 、我々は最終的に同じ場所に半ば、常にポイントを残し

これを防ぐために、我々は完全に組み込むことができます=左ミッド+(右-左)/ 2 + 1。 半ば意識的に右へ)

ACコード:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
      if (nums.size() == 0) return {-1, -1};
      // 找到第一个该数字出现的位置
      int i = 0, j = nums.size() - 1;
      while (i < j) {
        // 为什么这里不用加1?
        int m = i + (j - i) / 2;
        // 这种方式j始终在向target靠
        if (nums[m] >= target) j = m;   // j是后面的指针,这里是往前靠了
        else i = m + 1;      // 感觉挺巧妙的,这里i也自动向target靠了
        // 注意这里i指向的是不超过nums[m]的最大元素
      }
      int left;
      if (target == nums[j]) left = j;
      else return {-1, -1};
      // 找到最后一个该数字出现的位置
      i = 0, j = nums.size() - 1;
      while (i < j) {
        int m = i + (j - i) / 2 + 1;
        if (nums[m] > target) j = m - 1;
        else i = m;     // i是前面的指针,这里往后靠了
      }
      int right = i;
      return {left, right};
    }
};

その他の経験:

先に与えられたテンプレートは、終了条件は、+ 1 <右を残しています。そうする必要は全くありません

最後に、左と右の追加の書き込み処理があります。

正しい言葉遣いは私たちの目的を達成するために、半ばを変更することです。

公開された137元の記事 ウォン称賛19 ビュー10000 +

おすすめ

転載: blog.csdn.net/qq_43338695/article/details/102774935