비행기를 나누는 원


23

태스크

평면에 y = 0 선에 중심이있는 원 세트가 제공됩니다 . 원 쌍에 둘 이상의 공통점이 없습니다.

당신의 임무는 원이 평면을 나누는 영역의 수를 결정하는 것입니다. 영역은 원을 교차하지 않는 포함 최대 연속 포인트 집합입니다.

원에 대한 설명이 주어지면이 답변을 계산하는 프로그램을 작성해야합니다.


예를 들면 다음과 같습니다.

예 1

왼쪽에는 평면에 그려진 원이 표시됩니다. 그러나 그림의 오른쪽 절반에서 원으로 생성 된 영역은 명확하게 색상이 지정됩니다 (영역 당 하나의 색상). 이 예에는 6 개의 영역이 있습니다.


입력

입력의 첫 번째 줄에는 N뒤에 오는 원 설명의 개수 인 숫자가 포함 됩니다. 이 라인은 선택 사항입니다. 솔루션없이 솔루션을 사용하면 괜찮습니다.

다음 N두 정수를 포함하고, 각 라인은 X I를 그리고 r에 난을 > 0 , 중심 원을 나타내는 (X , 0) 과 반경 r에 난을 .

원 쌍에 둘 이상의 공통점이 없습니다. 이는 나아가 보장 X I를 그리고 r에 초과하지 않는다 10^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 증명할 수 없다면 불가능하다고 가정하지 마십시오.)
Niklas B.

음, 기계 정수에 맞는 입력이 보장되면 기수 정렬을 사용하여 O (n)이라고 부를 수 있습니다. 엄격하게 말해서, 가능한 많은 입력이 있음을 의미하기 때문에 제한된 입력 크기를 가정하는 것을 싫어합니다.
user2357112는

@ user2357112 아니요, 무증상을 평가하는 동안 정수를 제한한다고 가정 할 수 없으므로 기수 정렬이나 계산 정렬이 선형 시간과 공간이 될 수 없습니다. 단지를 arithmetics "진짜"O (1) 실제적인 이유 (대부분의 언어의 경계 가변 폭)하는 것입니다 그들은 단어에 맞
니클라스 B.

@NiklasB. 초 선형 복잡성을 가진 유일한 구성 요소가 정렬 인 알고리즘을 사용하는 경우 n log n보너스 를 얻기 위해 언어에서 빠른 정렬을 사용하는 경우 병합 정렬을 구현해야 합니까? 또한 새로운 개념의 새로운 솔루션이 있습니다. 이전 답변을 대체하는 새로운 답변을 게시해야합니까? (새 솔루션이 실제로 정확하지 않은 경우 전자를 선호합니다)
Martin Ender

답변:


2

매쓰, 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의 입력으로 방금 실행합니까?
Niklas B.

@NiklasB. 그의 입력 방법은 문자열 변수를 익명 함수에 전달하는 것입니다. 그래서 자격이 있다고 생각합니다. 출력과 관련하여 Mathematica에서는 콘솔 출력으로 숫자가 끝나기 때문에 결과도 좋을 것입니다.
Martin Ender

나는 이것의 정확성을 확인 했으므로 -28의 점수로 이것이 새로운 리더라고 생각합니다. 축하합니다!
Niklas B.

@NiklasB. 왜 150 만? 알고리즘의 어느 부분이 초 선형 최악의 복잡성을 가지고 있습니까?
Martin Ender

@ m.buettner 150은 O (n) 예상 시간입니다. 여기에 암시 적으로 정의 된 임의의 숫자를 노드로 갖는 그래프의 경우 선형 시간에 CC 수를 찾을 수 없으며 연결된 구성 요소에 대한 요소의 구별 을 줄여 표시 할 수 있습니다 . 또한 원래 문제에 대한 요소의 구별을 줄일 수 있다고 생각합니다
.

4

루비 - 312 306 285 273 269 259 자

이 답변은 훨씬 적은 문자를 사용 하고에서 실행 되는 다른 접근 방식 으로 대체되었습니다 .O(n log n)

알았어 가자 초보자에게는 방금 작동하는 구현을 원했기 때문에 아직 알고리즘 적으로 최적화되지 않았습니다. 나는 원을 가장 큰 것에서 가장 작은 것까지 정렬하고 나무를 만듭니다 (다른 원에 포함 된 원은 그 큰 원의 자식입니다). 두 작업 모두 O(n^2)최악의 상태에서 수행 됩니다 O(n log n). 그런 다음 나무를 반복하여 면적을 계산합니다. 원의 자식이 전체 지름을 채우면 두 개의 새로운 영역이 있고 그렇지 않으면 하나만 있습니다. 이 반복이 걸립니다 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

ungolfed 버전 (변수 입력이 예상 됨 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. 예, 테스트 케이스가 좋을 것입니다. 내 나무의 가장자리를 정의하는 관계는 단순히 하나의 원을 다른 원에 포함시키는 것입니다. 원이 서로를 포함하지 않는 두 원 ( "한 교차점"조건으로 인해)에 포함될 수 없기 때문에 이것이 어떻게 DAG가 될 수 있는지 알 수 없습니다.
마틴 엔더

노드의 손자도 자녀입니까?
user2357112는 Monica

@ user2357112 아니오, 직계 부모 만 분할 할 수 있기 때문에
Martin Ender

@NiklasB. 귀하의 질문에있는 예제로 실행하면을 얻습니다 11. 귀하의 의견에 하나 9.
Martin Ender

@NiklasB. 실제로 얻을, 대기 108내 ungolfed 버전 만 11하고 9내 현재 golfed 버전 : D
마틴 청산

2

루비 203 183 173 133-100 = 33 개 문자

여기 다른 접근법이 있습니다. 이번에는 가장 왼쪽 점을 기준으로 원을 정렬합니다. 가장 왼쪽에서 접하는 원은 가장 큰 것부터 가장 작은 것까지 정렬됩니다. 이 걸리는 O(n log n)(잘, 루비가 빠른 정렬, 그래서 실제로 사용 O(n^2)하지만 병합을 구현 / 힙 종류의 아마이 문제의 범위를 벗어납니다). 그런 다음이 목록을 반복하면서 내가 방문한 서클의 가장 왼쪽과 오른쪽 위치를 모두 기억합니다. 이를 통해 일련의 원이 둘러싸고있는 더 큰 원을 가로 질러 연결되는지 감지 할 수 있습니다. 이 경우 두 개의 하위 영역이 있으며 그렇지 않은 경우 하나만 있습니다. 이 반복은 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

ungolfed 버전 (변수의 입력이 예상 됨 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)에서 테스트 데이터를 찾을 수 있습니다
Niklas B.

첫 번째 실패한 테스트 케이스는 kruznice / kruznice.in.2이며 이는 첫 번째 "실제"테스트 케이스이므로 알고리즘 또는 구현에 근본적으로 잘못된 것이 있다고 가정합니다. 임의로 중첩 된 원에서 올바르게 작동합니까?
Niklas B.

@NiklasB. 감사합니다. 테스트 사례를 살펴 보겠습니다 (내일 밤까지 고칠 수 있습니다)
Martin Ender

@NiklasB. 나는 문제를 알아 냈고 최소 실패 예제에는 5 개의 원이 필요합니다 -1 1 1 1 0 2 4 2 0 6. 나는 내일 밤까지 이것을 고치는 방법에 대해 생각할 것이다.
Martin Ender

복잡도 분석은 연관 배열 액세스가 일정한 시간이라고 가정합니다. 최악의 경우에는 사실이 아닌 것 같습니다.
피터 테일러

1

줄리아-260-100 (bonus?) = 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.
Niklas B.

"한 쌍의 원이 둘 이상의 공통점을 갖는 것은 보장되지 않습니다." 그래서 나는 그것이 적용되지 않을 것이라고 생각합니다 :)
CCP

@CCP 공통점이 없습니다. n=2서클은 다음 (C=(-10,0), r=1)과 같습니다(C=(10,0), r=1)
Niklas B.

1
오일러 특성을 적용하기 위해 그래프를 연결하지 않아도됩니까?
user2357112는 Monica

1
아, 여기 간단한 사례가 있습니다. 4 0 2 1 1 10 2 11 1하지만 더 많은 테스트 사례를 줄 수는 없다고 생각합니다. 조금 불공평 할 것입니다
.

1

Spidermonkey JS, 308, 287 , 273-100 = 173

루비 또는 파이썬으로 이것을 다시 쓰면 문자를 저장할 수 있다고 생각합니다.

암호:

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)이라고 생각합니다 (그리고 O ( n log n) 그러나 사라짐). 이것이 결정 론적입니까?


누구든지 r루프와 l루프를 하나의 문장으로 결합하는 방법에 대한 조언이 있다면 감사하겠습니다.
찰스

건배 :) 당신의 런타임이 정렬로 인해 실제로 O (n log n) 인 것처럼 보입니다. 모든 테스트 사례를 통과했는지 알려 드리겠습니다.
Niklas B.

프로그램은 첫 번째 시도에서 모든 테스트 사례를 통과합니다. 나는 이와 같은 것 (일부 국가가 스택으로 유지되는 스위프 라인)이 문제 저자의 공식 솔루션이라고 생각합니다. 귀하의 프로그램의 총점은 173 점입니다
Niklas B.

@NiklasB. 감사!
아니 Charles Charles

나는 겹치는 원으로 훨씬 더 강력한 솔루션을 시도하고 있었는데 ... 한 지점에서만 교차 할 수 있음을 알았습니다.
Charles Charles

-1

자바 스크립트 (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)입니다.

내 할일 목록의 다음 항목을 추측하십시오 ... 150 자 미만의 버킷 정렬. 끝난


버킷 정렬에만 평균 복잡성을 가지고 O(n)(사실 O(n+k))하지만, O(n^2)또는 O(n log n)당신은 50 자에서 그것을 할 필요가 거라고 그래서 최악의 경우, 버킷 내에서 사용되는 정렬 알고리즘에 따라 달라집니다.
Martin Ender

@ m.buettner-버킷 정렬은 O (N) 최악의 경우 복잡성에서 수행 할 수 있습니다. 버킷을 신중하게 선택하고 버킷에 할당 할 O (1) 알고리즘을 사용합니다. 나는 그것을 전에하고 그것을 증명했고 코드를 JavaScript로 전송하면됩니다. 위의 알고리즘은 이미 O (N.log (N))이므로 유일한 개선은 O (N) 정렬 알고리즘을 얻는 것입니다.
MT0

그 증거와 그에 상응하는 버킷 선택에 관심이 있습니다. :)
Martin Ender 2016 년

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.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.