平面を分割する円


23

仕事

平面に円のセットが与えられ、中心が線y = 0になります。円のペアが複数の共通点を持たないことが保証されています。

あなたのタスクは、円が平面を分割する領域の数を決定することです。領域は、円のいずれとも交差しない包含最大連続点のセットです。

円の説明が与えられたときにこの答えを計算するプログラムを作成する必要があります。


以下に例を示します。

例1

左側には、平面に描かれた円があります。ただし、写真の右半分では、円によって生成される領域は明確に色付けされています(領域ごとに1色)。この例には6つの領域があります。


入力

入力の最初の行には、数字N、、続く円の説明の数が含まれています。この行はオプションです。ソリューションが機能しない場合は問題ありません。

次のN行にはそれぞれ2つの整数x iおよびr i > 0が含まれ、中心(x i、0)および半径r iの円を表します。

円のペアが複数の共通点を持たないことが保証されています。さらに、x ir i10^9絶対値を超えないことが保証されます(したがって、32ビット整数に快適に適合します)。


入力は次のとおりです。

  • STDINから読み取る

  • I現在のディレクトリにある名前のファイルから読み取る

または、入力は次のようになります。

  • グローバル変数の文字列(改行を含む)として利用可能

  • スタック上


出力

これは、生成されるリージョンの数である単一の整数でなければなりません。これは、STDOUTまたはO現在のディレクトリで指定されたファイルに書き込まれる必要があります。


ルール

  • バイト単位の最短コードが勝つ

  • コードにランタイム+スペース複雑度多項式がない場合、+ 200バイトのペナルティ n

  • 最悪の場合の予想ランタイム+スペースの複雑さに対する-100バイトのボーナス O(n log n)

  • 最悪の場合の予想ランタイム+スペースの複雑さに対する-50バイトのボーナス O(n)

  • 確定的なランタイム+スペースの複雑さに対する-100バイトのボーナス O(n)

ランタイムの評価中:

  • O(1)操作と入力データのシーケンスに関係なく、ハッシュテーブルに挿入、削除、およびルックアップのランタイムが必要であると想定します。これは、実装がランダム化を使用するかどうかに応じて、真である場合とそうでない場合があります。

  • プログラミング言語の組み込みソートには確定的なO(n log n)時間がかかると仮定します。ここnで、入力シーケンスのサイズです。

  • 入力数の算術演算にはO(1)時間がかかると仮定します。

  • 実用的な理由から、入力番号は定数でバインドされていると想定しないでください。つまり、基数ソートやカウントソートなどのアルゴリズムは線形時間ではありません。一般的に、非常に大きな一定の要因は避けるべきです。


入力:

2 
1 3
5 1

出力: 3


入力:

3
2 2
1 1
3 1

出力: 5

4
7 5
-9 11
11 9
0 20

入力:

9
38 14
-60 40
73 19
0 100
98 2
-15 5
39 15
-38 62
94 2

出力: 11


ヒント

非常にコンパクトなソリューションには、次のアイデアを使用できます。円のセットをX軸と交差させ、交差点を平面グラフのノードとして解釈します。

ここに画像の説明を入力してください

このグラフでは、すべての円が正確に2つのエッジと最大2つのノードを生成します。ハッシュテーブルを使用して、個別の左右の境界線の総数を追跡することで、ノードの数をカウントできます。

次に、オイラー特性式を使用して、グラフの描画の面の数を計算できます。

V - E + F - C = 1

F = E - V + C + 1

C接続されたコンポーネントの数を計算するには、深さ優先検索を使用できます。


注:この問題のアイデアは、最近のクロアチアのプログラミングコンテストから借用したものですが、ソリューションの概要を参照してごまかさないでください。:)


それらのボーナスのいくつかはおとりですか?
user2357112は

@ user2357112あなたがそれを証明できなければ、それができないと思い込まないでください;)
ニクラスB. 14年

さて、入力がマシンの整数に収まることが保証されているので、基数ソートを使用してO(n)と呼ぶことができます。厳密に言えば、入力可能な数が有限であるという意味なので、制限された入力サイズを想定するのは嫌です。
user2357112は

@ user2357112いいえ、漸近性の評価中に整数を制限することはできないと述べたため、基数ソートもカウントソートも線形の時間と空間ではありません。単語に収まるのは、算術演算を「実際の」O(1)にするためであり、実際的な理由(ほとんどの言語で制限された可変幅)
Niklas B. 14年

@NiklasB。超線形複雑性を持つ唯一のコンポーネントがソートであるアルゴリズムがある場合、n log nボーナスを得るために私の言語がクイックソートを使用している場合、マージソートを実装する必要がありますか?また、新しい概念的に新しいソリューションがあります。古い回答を置き換える新しい回答を投稿する必要がありますか?(私の新しい解決策が実際に正しくない場合のために、前者を好む)
マーティン・エンダー14年

回答:


2

Mathematica、125 122-150 = -28文字

私は組み込み関数の複雑さを知りませんConnectedComponents

1+{-1,2,1}.Length/@{VertexList@#,EdgeList@#,ConnectedComponents@#}&@Graph[(+##)<->(#-#2)&@@@Rest@ImportString[#,"Table"]]&

使用法:

1+{-1,2,1}.Length/@{VertexList@#,EdgeList@#,ConnectedComponents@#}&@Graph[(+##)<->(#-#2)&@@@Rest@ImportString[#,"Table"]]&[
"9
38 14
-60 40
73 19
0 100
98 2
-15 5
39 15
-38 62
94 2"]

11


ConnectedComponents最悪の複雑さが線形に予想されることを安全に想定できると思うので、O(n)コンポーネントがある場合はこれで問題ありません。私はMathematicaを理解していないので、全体としてO(n)であり、-150ボーナスの資格があるかどうかわかりませんか?そうだと思います。STDINで入力して実行するだけですか?
ニクラスB. 14年

@NiklasB。彼のインプットメソッドは、文字列変数を匿名関数に渡すだけです。資格があると思う 出力に関しては、Mathematicaでは単に数値がコンソール出力になりますので、おそらくそれでも問題ないはずです。
マーティンエンダー14年

これが正しいことを確認したので、-28のスコアでこれが新しいリーダーだと思います。おめでとうございます!
ニクラスB. 14年

@NiklasB。なぜ150だけですか?アルゴリズムのどの部分が超線形の最悪のケースの複雑さを持っていますか?
マーティンエンダー14年

@ m.buettner 150はO(n)の予測時間です。このように暗黙的に定義されたノードとして任意の数のグラフの場合、線形時間でCCの数を見つけることはできません。これは、要素の明確さを接続されたコンポーネントに減らすことで表示できます。元の問題
ニクラスB. 14年

4

ルビー- 312の 306 285 273 269 259文字

この答えは取って代わられている私の他のアプローチかなり少ない文字を使用してで実行されますO(n log n)

では行きましょう。まず、実用的な実装が必要だったため、これはまだアルゴリズム的に最適化されていません。円を最大から最小に並べ替えて、ツリーを構築します(他の円に含まれる円は、それらの大きい円の子です)。どちらの操作もO(n^2)、最悪の場合O(n log n)でも最高の場合でもかかります。次に、ツリーを反復処理して領域をカウントします。円の子がその直径全体を埋める場合、2つの新しい領域があります。それ以外の場合は1つだけです。この反復にはが必要O(n)です。したがって、私は全体的に複雑でO(n^2)あり、報酬も罰金も受けられません。

このコードは、円の数のない入力が変数に格納されることを想定していますs

t=[]
s.lines.map{|x|x,r=x.split.map &:to_i;{d:2*r,l:x-r,c:[]}}.sort_by!{|c|-c[:d]}.map{|c|i=-1;n=t
while o=n[i+=1]
if 0>d=c[:l]-o[:l]
break
elsif o[:d]>d
n=o[:c]
i=-1
end
end
n[i,0]=c}
a=1
t.map &(b=->n{d=0
n[:c].each{|c|d+=c[:d]}.map &b
a+=d==n[:d]?2:1})
p a

ゴルフされていないバージョン(変数への入力が期待されますstring):

list = []
string.split("\n").map { |x|
  m = x.split
  x,radius = m.map &:to_i
  list<<{x:x, d:2*radius, l:x-radius, r:x+radius, children:[]}
}
list.sort_by! { |circle| -circle[:d] }
tree = []
list.map { |circle|
  i = -1
  node = tree
  while c=node[i+=1]
    if circle[:x]<c[:l]
      break
    elsif circle[:x]<c[:r]
      node = c[:children]
      i = -1
    end
  end
  node[i,0] = circle
}
areas = 1
tree.map &(count = -> node {
  d = 0
  i = -1
  while c=node[:children][i+=1]
    count.call c
    d += c[:d]
  end
  areas += d == node[:d] ? 2 : 1
})
p areas

@NiklasB。はい、そのテストケースがいいでしょう。私のツリーのエッジを定義する関係は、単純にある円を別の円に含めることです。(「1つの交差点」条件のため)互いに含まれない2つの円にon circleを含めることはできないため、これがDAGになる方法はわかりません。
マーティンエンダー14年

ノードの孫もその子ですか?
user2357112は

@ user2357112いいえ、直接の親のみを分割できるため
Martin Ender 14年

@NiklasB。あなたの質問の例を使用して実行すると、が表示されます11。あなたのコメントにあるものについて9
マーティンエンダー14年

@NiklasB。待ち時間、私は実際に取得10し、8私のungolfedバージョンではなく、11そして9私の現在のgolfedバージョンと:D
マーティン・エンダー

2

ルビー、203 183 173 133から100 = 33の文字

そのため、ここに別のアプローチがあります。今回は、一番左のポイントで円を並べ替えます。一番左の点で接触している円は、大きい順に並べられます。これには時間がかかりますO(n log n)(Rubyはクイックソートを使用するため、実際にO(n^2)はマージ/ヒープソートの実装はおそらくこの課題の範囲外です)。次に、このリストを繰り返し処理して、訪れたサークルの左端と右端の位置をすべて記憶します。これにより、一連の円が、より大きな円を囲むように接続されているかどうかを検出できます。この場合、2つのサブエリアがあり、それ以外の場合は1つだけです。このイテレーションでは、100文字の報酬を得るために必要なO(n)複雑さの合計のみをO(n log n)取得します。

このスニペットは、円の数なしで、コマンドライン引数のファイルを介して入力が提供されることを想定しています。

l,r={},{}
a=1
$<.map{|x|c,q=x.split.map &:to_r;[c-q,-2*q]}.sort.map{|x,y|a+=r[y=x-y]&&l[x]?2:1
l[y]=1 if l[x]&&!r[y]
l[x]=r[y]=1}
p a

ゴルフされていないバージョン(変数への入力が期待されますstring):

list = []
string.split("\n").map { |x|
  m = x.split
  x,radius = m.map &:to_r
  list<<{x:x, d:2*radius, l:x-radius, r:x+radius}
}
list.sort_by! { |circle| circle[:l] + 1/circle[:d] }
l,r={},{}
areas = 1
list.map { |circle|
  x,y=circle[:l],circle[:r]
  if l[x] && r[y]
    areas += 2
  else
    areas += 1
    l[y]=1 if l[x]
  end
  r[y]=1
  l[x]=1
}
p areas

残念ながら、これはすべての大規模なテストケースで失敗します。私はこの時、小さな失敗例を持っていませんが、私は(それのコンテスト#6)にリンクされているコンテストのウェブサイト上のテストデータを見つけることができます);これは、しかし速いです
ニクラスB.

最初に失敗するテストケースはkruznice / kruznice.in.2で、これが最初の「実際の」テストケースであるため、アルゴリズムまたは実装に根本的な問題があると思います。任意にネストされた円で正しく動作しますか?
ニクラスB. 14年

@NiklasB。おかげで、テストケースを見ることができます(ただし、それを修正するために明日の夜まで連れて行ってくれるかもしれません)
マーティンエンダー14年

@NiklasB。問題を理解し、最小の失敗例には5つの円が必要です-1 1 1 1 0 2 4 2 0 6。明日の夜までにこれを修正する方法を考えます(うまくいけば)。
マーティンエンダー14年

複雑さの分析では、連想配列へのアクセスは一定時間であると想定しているようです。最悪の場合、それは真実ではないようです。
ピーターテイラー14年

1

ジュリア-260-100(ボーナス?)= 160

円を頂点(交差)、エッジ、および面(平面の領域)を持つ図形として解釈すると、オイラー特性を使用して相互に関連付けることができるため、「頂点」と「エッジ」の数だけを知っていれば、 「顔」または平面の領域の以下の式で:オイラー特性

更新:しばらく考えると、私の方法の問題は、接続されていないサークルだけであることがわかったので、アイデアを思いついたのはなぜですか?したがって、全体がオイラーの式を満たします。

円の例

F = 2 + EV(V = 6、E = 9)

[入れ子になった円では動作しないので、一般的な場合の問題の答えではありません]

コード

s=readlines(open("s"))
n=int(s[1])
c=zeros(n,2)
t=[]
for i=1:n
    a=int(split(s[i+1]))
    c[i,1]=a[1]-a[2]
    c[i,2]=a[1]+a[2]
    if i==1 t=[c[1]]end
    append!(t,[c[i,1]:.5:c[i,2]])
end
e=0
t=sort(t)
for i in 1:(length(t)-1) e+=t[i+1]-t[i]>=1?1:0end #adds one edge for every gap
2+2n+e-length(unique(c)) # 2+E-V = 2+(2n+e)-#vertices

あなたのプログラムは失敗すると思います2 -10 1 10 1
ニクラスB. 14年

「1組の円に複数の共通点がないことが保証されています。」だから私はそれが適用されないと思う:)
CCP 14年

@CCP共通点はありません。n=2、円である(C=(-10,0), r=1)(C=(10,0), r=1)
のNiklas B.

1
オイラー特性を適用するためにグラフを接続する必要はありませんか?
user2357112は、Monica 14年

1
ああ、ここでは単純なケースである。4 0 2 1 1 10 2 11 1しかし、私は少し不公平だろうと、私はあなたに多くのテストケースを与えることができるとは思わない
ニクラスB.

1

SpiderMonkeyのJS、308、287、273 - 173 = 100

RubyまたはPythonでこれを書き直せば、キャラクターを保存できると思います。

コード:

for(a=[d=readline],e={},u=d(n=1);u--;)[r,q]=d().split(' '),l=r-q,r-=-q,e[l]=e[l]||[0,0],e[r]=e[r]||[0,0],e[r][1]++,e[l][0]++
for(k=Object.keys(e).sort(function(a,b)b-a);i=k.pop();a.length&&a.pop()&a.push(0)){for([l,r]=e[i];r--;)n+=a.pop()
for(n+=l;l--;)a.push(l>0)}print(n)

アルゴリズム:

n = 1 // this will be the total
e = {x:[numLeftBounds,numRightBounds]} // imagine this as the x axis with a count of zero-crossings
a = [] // this is the stack of circles around the "cursor".  
       // values will be 1 if that circle's never had alone time, else 0
k = sort keys of e on x
for each key in k: // this is the "cursor"
  n += key[numLeftBounds] // each circle that opens has at least one space.
  k[numRightBounds].times {n += a.pop()} // pop the closing circles. if any were never alone, add 1
  k[numLeftBounds].times {a.push(alwaysAlone)} // push the opening circles
  if !a.empty():
     set the innermost circle (top of stack) to false (not never alone)
  fi
loop

私は大きなO表記法はそれほど得意ではありませんが、各円を効果的に3回ループ(作成、左、右)し、マップのキーを並べ替える(そしてO( n log n)しかしそれは消えます)。これは決定論的ですか?


rループとlループを1つのステートメントに結合する方法についてアドバイスがあれば、感謝します。
チャールズチャールズ14年

乾杯:)ソートが-100になるため、ランタイムは確かにO(n log n)のように見えます。すべてのテストケースに合格したかどうかをお知らせします。
ニクラスB.

素晴らしい、あなたのプログラムは最初の試行ですべてのテストケースに合格します。私は、このような何か(スタックにいくつかの状態が維持されているスイープライン)が問題の著者による公式の解決策だったと思います。プログラムの合計スコアは173
ニクラスB。14年

@NiklasB。ありがとう!
チャールズチャールズ14年

円が重なる、はるかに堅牢なソリューションを試してみました。その後、1つの点でしか交差できないことがわかりました。
チャールズチャールズ14年

-1

JavaScriptの(ES6) - 255の 254文字- 100回の 250ボーナス= 155 4

R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

入力文字列が変数内にあるSと想定し、リージョンの数をコンソールに出力します。

R=/(\S+) (\S+)/ym;                  // Regular expression to find centre and width.
N=1;                                // Number of regions
w=l=0;                              // Maximum width and minimum left boundary.
X=[];                               // A 1-indexed array to contain the circles.
                                    // All the above are O(1)
for(;m=R.exec(S);){                 // For each circle
    X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};
                                    // Create an object with w (width), l (left boundary)
                                    // and r (right boundary) attributes.
    l=k<l?k:l;                      // Update the minimum left boundary.
    w=j<w?w:j                       // Update the maximum width.
}                                   // O(1) per iteration = O(N) total.
M=[];                               // An array.
X.map(x=>M[(x.l-l+1)*w-x.w]=x);     // Map the 1-indexed array of circles (X) to a
                                    // sparse array indexed so that the elements are
                                    // sorted by ascending left boundary then descending
                                    // width.
                                    // If there are N circles then only N elements are
                                    // created in the array and it can be treated as if it
                                    // is a hashmap (associative array) with a built in
                                    // ordering and as per the rules set in the question
                                    // is O(1) per insert so is O(N) total cost.
                                    // Since the array is sparse then it is still O(N)
                                    // total memory.
s=[];                               // An empty stack
i=0;                                // The number of circles on the stack.
M.map(x=>{                          // Loop through each circle
    while(i&&s[i-1][1]<x[1])        // Check to see if the current circle  is to the right
                                    // of the circles on the stack;
      N+=s[--i][0]?0:1;             // if so, decrement the length of the stack and if the
                                    // circle that pops off has radius equal to the total
                                    // radii of its children then increment the number of
                                    // regions by 1.

                                    // Since there can be at most N items on the stack then
                                    // there can be at most N items popped off the stack
                                    // over all the iterations; therefore this operation
                                    // has an O(N) total cost.
    i&&(s[i-1][0]-=x[0]);           // If there is a circle on the stack then this circle
                                    // is its child. Decrement the parent's radius by the
                                    // current child's radius.
                                    // O(1) per iteration
    s[i++]=x                        // Add the current circle to the stack.
  });
while(i)N+=s[--i][0]?0:1            // Finally, remove all the remaining circles from the
                                    // stack and if the circle that pops off has radius
                                    // equal to the total radii of its children then
                                    // increment the number of regions by 1.
                                    // Since there will always be at least one circle on the
                                    // stack then this has the added bonus of being the final
                                    // command so the value of N is printed to the console.
                                    // As per the previous comment on the complexity, there
                                    // can be at most N items on the stack so between this
                                    // and the iterations over the circles then there can only
                                    // be N items popped off the stack so the complexity of
                                    // all these tests on the circles on the stack is O(N).

時間の複雑さはO(N)になりました。

テストケース1

S='2\n1 3\n5 1';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

出力: 3

テストケース2

S='3\n2 2\n1 1\n3 1';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

出力: 5

テストケース3

S='4\n7 5\n-9 11\n11 9\n0 20';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

出力: 6

テストケース4

S='9\n38 14\n-60 40\n73 19\n0 100\n98 2\n-15 5\n39 15\n-38 62\n94 2';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

出力: 11

テストケース5

S='87\n-730 4\n-836 2\n-889 1\n-913 15\n-883 5\n-908 8\n-507 77\n-922 2\n-786 2\n-782 2\n-762 22\n-776 2\n-781 3\n-913 3\n-830 2\n-756 4\n-970 30\n-755 5\n-494 506\n-854 4\n15 3\n-914 2\n-840 2\n-833 1\n-505 75\n-888 10\n-856 2\n-503 73\n-745 3\n-903 25\n-897 1\n-896 2\n-848 10\n-878 50\n-864 2\n0 1000\n-934 6\n-792 4\n-271 153\n-917 1\n-891 3\n-833 107\n-847 3\n-758 2\n-754 2\n-892 2\n-738 2\n-876 2\n-52 64\n-882 2\n-270 154\n-763 3\n-868 72\n-846 4\n-427 3\n-771 3\n-767 17\n-852 2\n-765 1\n-772 6\n-831 1\n-582 2\n-910 6\n-772 12\n-764 2\n-907 9\n-909 7\n-578 2\n-872 2\n-848 2\n-528 412\n-731 3\n-879 1\n-862 4\n-909 1\n16 4\n-779 1\n-654 68\n510 490\n-921 3\n-773 5\n-653 69\n-926 2\n-737 3\n-919 1\n-841 1\n-863 3';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

出力: 105

前のバージョン

C=S.split('\n');N=1+C.shift()*1;s=[];C.map(x=>x.split(' ')).map(x=>[w=x[1]*1,x[i=0]*1+w]).sort((a,b)=>(c=a[1]-2*a[0])==(d=b[1]-2*b[0])?b[0]-a[0]:c-d).map(x=>{while(i&&s[i-1][1]<x[1])N+=s[--i][0]?0:1;i&&(s[i-1][0]-=x[0]);s[i++]=x});while(i)N+=s[--i][0]?0:1

コメント付き:

C=S.split('\n');                    // Split the input into an array on the newlines.
                                    // O(N)
N=1+C.shift()*1;                    // Remove the head of the array and store the value as
                                    // if there are N disjoint circles then there will be
                                    // N+1 regions.
                                    // At worst O(N) depending on how .shift() works.
s=[];                               // Initialise an empty stack.
                                    // O(1)
C .map(x=>x.split(' '))             // Split each line into an array of the two values.
                                    // O(1) per line = O(N) total.
  .map(x=>[w=x[1]*1,x[i=0]*1+w])    // Re-map the split values to an array storing the
                                    // radius and the right boundary.
                                    // O(1) per line = O(N) total.

  .sort((a,b)=>(c=a[1]-2*a[0])==(d=b[1]-2*b[0])?b[0]-a[0]:c-d)
                                    // Sort the circles on increasing left boundary and
                                    // then descending radius.
                                    // O(1) per comparison = O(N.log(N)) total.
  .map(x=>{                         // Loop through each circle
    while(i&&s[i-1][1]<x[1])        // Check to see if the current circle  is to the right
                                    // of the circles on the stack;
      N+=s[--i][0]?0:1;             // if so, decrement the length of the stack and if the
                                    // circle that pops off has radius equal to the total
                                    // radii of its children then increment the number of
                                    // regions by 1.

                                    // Since there can be at most N items on the stack then
                                    // there can be at most N items popped off the stack
                                    // over all the iterations; therefore this operation
                                    // has an O(N) total cost.
    i&&(s[i-1][0]-=x[0]);           // If there is a circle on the stack then this circle
                                    // is its child. Decrement the parent's radius by the
                                    // current child's radius.
                                    // O(1) per iteration
    s[i++]=x                        // Add the current circle to the stack.
  });
while(i)N+=s[--i][0]?0:1            // Finally, remove all the remaining circles from the
                                    // stack and if the circle that pops off has radius
                                    // equal to the total radii of its children then
                                    // increment the number of regions by 1.
                                    // Since there will always be at least one circle on the
                                    // stack then this has the added bonus of being the final
                                    // command so the value of N is printed to the console.
                                    // As per the previous comment on the complexity, there
                                    // can be at most N items on the stack so between this
                                    // and the iterations over the circles then there can only
                                    // be N items popped off the stack so the complexity of
                                    // all these tests on the circles on the stack is O(N).

合計時間の複雑さは、O(N.log(N))であるソートを除くすべてのO(N)です。ただし、これをバケットソートに置き換えると、総複雑さはO(N)に減少します。

必要なメモリはO(N)です。

TODOリストの次の項目を推測してください。150文字未満のバケットソートです。完了


バケットの並べ替えの複雑さO(n)(実際O(n+k))は平均しかありませんがO(n^2)O(n log n)最悪の場合はバケット内で使用される並べ替えアルゴリズムによって異なるため、50文字で行う必要があります。
マーティンエンダー14年

@ m.buettner-バケットのソートは、O(N)最悪の複雑さで実行できます。バケットの慎重な選択と、バケットに割り当てるO(1)アルゴリズムに依存しています。私は以前にそれを行い(そしてそれを証明しました)、コードをJavaScriptに転送するだけです。上記のアルゴリズムはすでにO(N.log(N))であるため、唯一の改善点はO(N)ソートアルゴリズムを取得することです。
MT0 14年

その証拠とそれに対応するバケットの選択に興味があります。:)
マーティンエンダー14年

cs.princeton.edu/~dpd/Papers/SCG-09-invited/…(556ページ)に、O(N)バケットの並べ替えの例を示します。archive.org/stream/PlanarityTestingByPathAddition/…(75ページ)に、O(N)を組み合わせたDFS検索とバケットソートの例を示します(時間の複雑さについては、76ページで説明します)。
MT0

1
@ Mt0はそこを保持しています。質問の複雑さのセクションへの私の追加を読むかもしれません。無制限の数を線形時間でソートすることは、間違いなく不可能です。
Niklas B. 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.