-1

重複の可能性:
間隔の
和集合間隔を効率的にオーバーラップする方法

間隔のリストがすべての整数であるとすると、それらが交差またはオーバーラップする場合は1つの間隔に折りたたむことができるはずです。そうでない場合、指定された間隔は影響を受けません。たとえば、入力がegI [(2-6)、(1-4)、(8-12)]の場合、期待される出力は[(1-6)、(8-12)]、たとえばII [(4- 7)、(2-6)、(1-4)、(8-12)、(7-9)]期待される出力は[(1-12)]です。

訂正:ソート部分が欠落しているため、はい、O(n)ではなくO(nlogn)時間です。それを指摘してくれてありがとう。私は、O(nlogn)時間とO(2n)空間アルゴリズムのアプローチを作成してテストしました。このアプローチのコードを以下で共有します。私は、この問題を解決するためのさまざまなアプローチ、おそらくより効率的な方法を聞くことに興味があります。

//各間隔(2〜6)などが「間隔」オブジェクト(以下に示すクラス定義)として表されると仮定します。ここで、low=2およびhigh=6 //ステップ1:指定された下限エンドポイントで並べ替えます区間//ステップ2:ソートされた区間のユニオンを見つける

//入力:

List<Interval> intervalList = new ArrayList<Interval>(); 

//出力:

List<Interval> unionList = new ArrayList<Interval>();    

private static final Comparator<Interval> Low_EPSorter = new LowEPSorter();

class Interval {
  int low, high;

  Interval(int l, int h, int m) {
    low = l;
    high = h;
  }
}

//// ------- BEGIN:指定された間隔のユニオンを見つけるメソッド---- //////

void UnionOfIntervals() {
  //Find intersection and combine intervals as necessary
  int sz = intervalList.size();

  // sort by low endpoint
  Collections.sort(intervalList, Low_EPSorter);

      for(int i = 0; i < sz; i++) {
        int j = i;
        if(j > 0) {
          if( Intervals.intersect(intervalList.get(j), intervalList.get(j-1)) ) {
            Interval v = union(intervalList.get(j), intervalList.get(j-1));
            checkAndAdd(v, unionList);
          }
          else {
            if(i == 1) {
              unionList.add(intervalList.get(j-1));
              unionList.add(intervalList.get(j));
          }
          else {
            unionList.add(intervalList.get(j));
          }
        } //No intersection
      } //If 2 elements atleast
      }

      //Print intervals after union
      System.out.println("Input intervals after sorting:");
      for(Interval v : intervalList) {
        System.out.print(v.low + "," + v.high + " ");
      }
      System.out.println();
      System.out.println("Union of intervals:");
      for(Interval v : unionList) {
        System.out.print(v.low + "," + v.high + " ");
      }
    }

    void checkAndAdd(Interval x, List t) {
      int top = t.size()-1;
      if( top >=0 && Intervals.intersect(unionList.get(top), x) ) {
        Interval v = union(unionList.get(top), x);
        t.remove(top);
        t.add(v);
      }
      else {
        t.add(x);
      }
    }

//// ------- END:指定された間隔のユニオンを見つけるメソッド---- //////

////---ヘルパーメソッド---////

static boolean intersect(Interval a, Interval b) {
      boolean r = false;
      if(b.high < a.low || b.low > a.high)
        r = false;
      else if(a.low <= b.high && b.low <= a.high)
        r = true;
      return r;
}

Interval union(Interval a, Interval b) {
      int l = (a.low < b.low) ? a.low : b.low;
      int max = (a.high > b.high) ? a.high : b.high;
      return new Interval(l, max);
}

private static class LowEPSorter implements Comparator<Interval> {

      public int compare(Interval a, Interval b) {
        int r = 0;
        if(a.low < b.low)
          r = -1;
        else if(a.low > b.low)
          r = 1;
        return r;
      }

}
4

4 に答える 4

1

サイズn(nは最大数)の配列を取り、間隔の開始と終了をそれぞれ1と-1で埋めます。

これは、間隔が

{[1-4],[6-8]} 

次に、配列要素は次のようになります

array[1]=1,array[4]=-1,array[6]=1,array[8]=-1

残りの配列の他のすべての場所はゼロに設定されます。

次に、配列をトラバースし、配列をスキャンすることで、ケースのように間隔を取得できます。

{[1-4],[2-5],[7-9]},

最初に上記のように配列を埋めます。配列Aは次のようになります(開始インデックスが1であると仮定)。

A=[1,1,0,-1,-1,0,1,0,1]

次に、配列Aを最初からトラバースし、変数sum = 0を取得して、配列の位置に格納されている値をsumに追加します。

配列の各インデックスでの合計の記述:

場所1:合計= 1(インデックス1で1)

場所2:合計= 2(インデックス2で1)

場所3:合計= 2(インデックス3では0)

場所4:合計= 1(インデックス4で-1)

場所5:合計= 0(インデックス5で-1)

合計がゼロに達すると、間隔がここで終了するため、新しい間隔は[1-5]になります。

場所6の場合:合計= 0(インデックス6の場合は0)

場所7:合計= 1(インデックス7で1)

(場所7では、合計が再びゼロより大きくなります。これは、間隔が開始されたばかりであることを意味します)

場所8の場合:合計= 1(インデックス8の場合は0)

場所9:合計= 0(インデックス9で-1)

場所7で開始された間隔は終了したばかりなので、新しい間隔範囲は次のようになります。

{[1-5],[7-9]}

それが役に立てば幸い。

于 2012-09-11T19:21:53.970 に答える
0

ちょうど別のアイデア:

  • ブール配列を使用する
    • デフォルトですべての値をfalseにします
    • (入力の)すべての間隔で値をtrueにします
    • 更新された配列をスキャンして、交差した最終結果を取得します。
于 2012-09-10T17:42:54.797 に答える
0

この問題に対して O(n) よりも効率的なアルゴリズムを探している場合、それが見つかるとは思えません。初期間隔値を保存するために使用するデータ構造に関係なく、最悪のシナリオは、間隔が重複せず、これを確認するために各間隔をチェックする必要があるため、O(n) です。aHashMapと非常に精巧なキー構造を使用しても、まだ O(n) を見ています。

そうは言っても、可能な限り最高の時間で解決するアルゴリズムO(n)をすでに見つけているので、他のアプローチを調査する価値があるかどうかはわかりません。

于 2012-09-10T17:22:55.070 に答える
0

アイデア: 交差しない間隔のセットを管理します。空のセットから始めて、着信間隔を追加します。新しい間隔が 1 つまたは 2 つの既存の間隔と交差する場合は、それらを結合します。交差を計算するには、同じ間隔のセットを参照する 2 つの TreeMap を使用しますが、異なるキー (下限と上限) を使用します。

于 2012-09-10T17:23:48.017 に答える