C ++
 Computer >> コンピューター >  >> プログラミング >> C ++

C++の範囲モジュール


範囲モジュールが必要だとします。これは、数値の範囲を追跡するモジュールです。私たちの仕事は、次のインターフェースを効率的に設計および実装することです。

  • addRange(左、右)。これにより、ハーフオープン間隔[左、右)が作成され、その間隔内のすべての実数が追跡されます。現在、現在追跡されている番号と部分的に重複する間隔を追加すると、まだ追跡されていない番号が間隔に追加されるはずです。
  • queryRange(left、right)。これは、間隔[左、右)のすべての実数が現在追跡されているときにtrueを返します。
  • removeRange(left、right)、これにより、間隔[left、right)で現在追跡されているすべての実数の追跡が停止します。

これを解決するには、次の手順に従います-

  • 1つのマップを定義するm
  • 関数addRange()を定義します。これは、左、右になります。
  • removeRange(left、right)
  • m [左]:=右
  • it:=左がmにある場所
  • mの最初の要素と等しくなく、前の要素の2番目の値が左と同じである場合、-
    • (1つ減らします)
    • 2番目:=正しい
    • mから左を削除
  • mの最後の要素の前と等しくなく、次の最初の要素が右と同じである場合、-
    • その2番目:=次の2番目(それ)
    • mからnext(it)を削除
  • 関数queryRange()を定義します。これは、左、右になります。
  • it:=mのサブパートの場所はすべて左よりも小さい値です
  • mが空であるか、mの最初の要素と同じである場合、-
    • falseを返す
  • (1つ減らします)
  • 2番目のときにtrueを返す>=右
  • 関数removeRange()を定義します。これは、左、右になります。
  • mが空の場合、-
    • 戻る
  • it:=mのサブパートの位置すべて左より上の値
  • mの最初の要素と等しくない場合、-
    • (1つ減らします)
  • 配列を定義するv
  • while(mの最後の要素とその最初の要素
  • 最初の<左と2番目の>左の場合、-
    • temp:=2番目の
    • 2番目:=左
    • temp> rightの場合、m [right]:=temp
  • それ以外の場合、最初の場合> =左、次に-
    • vの最後に最初に挿入します
    • その2番目が正しい場合>正しい場合、-
      • m [right]:=2番目の
  • (1つ増やします)
  • iを初期化する場合:=0、i
  • mからv[i]を削除
  • 理解を深めるために、次の実装を見てみましょう-

    #include <bits/stdc++.h>
    using namespace std;
    class RangeModule {
    public:
       map <int, int> m;
       RangeModule() {
       }
       void addRange(int left, int right) {
          removeRange(left, right);
          m[left] = right;
          map <int, int> :: iterator it = m.find(left);
          if(it != m.begin() && prev(it)->second == left){
             it--;
             it->second = right;
             m.erase(left);
          }
          if(it != prev(m.end()) && next(it)->first == right){
             it->second = next(it)->second;
             m.erase(next(it));
          }
       }
       bool queryRange(int left, int right) {
          map <int, int> :: iterator it = m.upper_bound(left);
          if(m.empty() || it == m.begin())return false;
          it--;
          return it->second >= right;
       }
       void removeRange(int left, int right) {
          if(m.empty())return;
          map <int, int> :: iterator it = m.lower_bound(left);
          if(it != m.begin())it--;
          vector <int> v;
          while(it != m.end() && it->first < right){
             if(it->first < left && it->second > left){
                int temp = it->second;
                it->second = left;
                if(temp > right){
                   m[right] = temp;
                }
             }else if(it->first >= left){
                v.push_back(it->first);
                if(it->second > right){
                   m[right] = it->second;
                }
             }
             it++;
          }
          for(int i = 0; i < v.size(); i++){
             m.erase(v[i]);
          }
       }
    };
    main(){
       RangeModule ob;
       ob.addRange(10,20);
       ob.removeRange(14,16);
       cout << (ob.queryRange(10,14)) << endl;
       cout << (ob.queryRange(13,15)) << endl;
       cout << (ob.queryRange(16,17));
    }

    入力

    Add range (10,20)
    Remove Range (14,16)
    Check ranges (10,14), (13,15), (16,17)

    出力

    1
    0
    1

    1. C++での二分木の境界

      二分木があるとすると、ルートから反時計回りにその境界の値を見つける必要があります。ここでの境界には、左側の境界、葉、右側の境界が含まれ、ノードが重複することはありません。 左側の境界は、ルートから左端のノードまでのパスです。 右の境界は、ルートから右端のノードまでのパスです。 ルートに左サブツリーまたは右サブツリーがない場合、ルート自体は左境界または右境界になります。 したがって、入力が次のような場合 その場合、出力は[1,2,4,7,8,9,10,6,3]になります。 これを解決するには、次の手順に従います- 配列retを定義する 関数leftB

    2. C++での最大二分木

      整数配列があるとします。その配列内のすべての要素は一意です。この配列での最大ツリー構築は、次のように定義されます- ルートは配列内の最大数を保持します。 左側のサブツリーは、サブアレイの左側を最大数で割って構築された最大ツリーです。 右側のサブツリーは、サブアレイの右側を最大数で割って構築された最大ツリーです。 最大の二分木を構築する必要があります。したがって、入力が[3,2,1,6,0,5]の場合、出力は-になります。 これを解決するには、次の手順に従います- Solve()というメソッドを定義します。これにより、リストと左右の値が取得されます。関