O (1) 푸시 / 팝 시간으로 3 개의 스택을 하나의 배열로 구현할 수 있습니까?


9

고정 된 크기의 배열 하나를 사용하여 두 개의 스택을 효율적으로 구현할 수 있습니다. 스택 # 1은 왼쪽 끝에서 시작하여 오른쪽으로 커지고 스택 # 2는 오른쪽 끝에서 시작하여 왼쪽으로 커집니다. 세 개의 스택에 대해서도 동일합니까?

보다 구체적으로, 다음과 같은 조건에서 3 개의 스택을 구현할 수 있습니다.

  1. N 개의 개체를 담을 수있는 고정 크기 배열이 있습니다.
  2. 세 스택 크기의 합이 <N 인 한 push ()는 실패하지 않아야합니다.
  3. push () 및 pop () 작업 모두 O (1) 시간이 걸립니다.
  4. 배열 외에도 O (1) 추가 공간 만 사용할 수 있습니다.

이러한 요구 사항을 충족 하지 않는 솔루션의 예는 다음과 같습니다 .

  • 어레이를 3 개의 고정 부품으로 분할하고 스택에 각 부품을 사용합니다 (2를 위반).
  • 위와 비슷하지만 스택 사이에 움직일 수있는 경계가 있습니다 (3을 위반).
  • 간단한 연결 목록 기반 구현 (4 위반)

푸시 / 팝이 O (1) 할부 상환 시간을 걸리는 알고리즘 또는 추가 메모리는 O (N)보다 작습니다 (예 : O (log N)). 또는 예를 들어 푸시 / 팝당 5 개 미만의 어레이 요소에 액세스하는 것이 불가능하다는 것을 보여주는 불가능한 증거입니다.


1
이것을 요구 사항 4의 위반으로 간주하는지 모르겠지만 N 객체 배열의 각 "개체"에 정수 색인과 같은 추가 필드가 포함될 수 있다면 배열 내부에 "연결된 목록"을 구현할 수 있습니다 . 3 개의 외부 변수를 사용하여 3 개의 스택 각각의 최상위 인덱스를 보유 할 수 있으며 각 "개체"는 해당 스택의 이전 요소를 가리킬 수 있습니다.
Avi Tal

"객체"란 push ()가 받아들이고 pop ()이 반환하는 것을 의미했습니다. 스택 구현의 관점에서 볼 때 불투명 한 데이터 덩어리입니다 (예 : 개체는 32 비트 정수일 수 있음). 스택 구현은 이러한 객체를 어떤 식 으로든 수정해서는 안됩니다.
user1020406

1
먼저 일련의 작업을 고려하십시오. 푸시 조작 후 팝 조작 만 수행하십시오. 이 버전의 문제에 대해 알려진 것이 있습니까?
Dmitri Urbanowicz

할 것이다 영형()추가 공간이 당신을 만족?
Dmitri Urbanowicz의

Re : "N을 누른 다음 N을 팝"버전 : 잘 모르겠지만 O (1) 솔루션이 가능한지 확실하지 않기 때문에이를 흥미로운 하위 문제로 식별하는 것도 유용합니다. @Alexei의 답변과 상한에 대한 주석 스레드를 참조하십시오. 에 관해서는영형()해결책, 그렇습니다 나는 받아 들일 것입니다. 나는 stackexchange에 대한 질문을 처음 접했으므로 시간이 지남에 따라 더 나은 솔루션을 제공 할 수있는 경우를 처리하는 방법을 모르겠습니다. 내가 본 한 가지 접근법은 더 나은 것이 게시 될 경우 답변을 수락하기 전에 하루 정도 기다려야한다는 것이므로 그렇게 할 것입니다.
user1020406

답변:


6

Fredman과 Goldsmith는 "Three Stacks"(저널 알고리즘, 1994)에서 Θ(ε)낭비되는 공간을 얻을 수 있습니다. 또한 최소 16 개의 쿼터 오실 론 요타 바이트 크기의 어레이에 필요한 최소값입니다. 간단한 알고리즘 낭비를 설명했습니다Θ() 내 StackOverflow 의 공간 단어 가이 질문에 대답합니다 . @ dmitri-urbanowicz가 주석에서 언급했듯이 이것은 기본적으로 배열을 다음과 같이 취급합니다. 크기의 블록 여기서 각 블록은 정확히 하나의 스택에 사용되고 해당 스택의 다음 블록에 대한 단일 포인터를 포함합니다.


0

N을 기본 배열의 길이라고하자. 스택을 큰 청크의 연결된 목록으로 상상할 수 있으므로 전체 청크 수가 O (log2 (N))를 넘지 않아야합니다. N / 2의 인덱스에서 첫 번째 두 스택 사이에 세 번째 스택을 놓습니다. 따라서 3 개의 점유 공간과 2 개의 무료 공간이 있습니다. 스택이 다음 요소를 수용 할 수 없으면 하나의 빈 영역이 소진되었음을 의미합니다. 다른 쪽도 소진되면 전체 메모리가 소진됩니다. 그렇지 않으면 크기가 N / 2 이하인 다른 빈 영역이 있습니다. 빈 공간으로 넘친 스택을 계속하십시오. 전체 구성이 스택의 초기 레이아웃과 유사합니다. 사용 가능한 메모리는 이제 초기의 절반을 넘지 않기 때문에 이러한 연결 작업의 log2 (N) 이상은 없습니다. 각 연결 작업에는 스택의 이전 상태를 저장하기 위해 고정 된 양의 메모리가 필요합니다. 그래서,


1
큰 덩어리 중 하나에서 물건을 터뜨려 얻은 메모리를 어떻게 재활용합니까?
Emil Jeřábek

좋은 질문. 빠른 대답은 여유가 된 청크가 이전에 가져온 여유 영역으로 메모리를 반환한다는 것입니다. 그러나 해당 청크에 대한 할당 메모리 시간 이후 빈 영역이 줄어들고 청크가 인접하지 않으면 어떻게 될까요? 이로 인해 사용 가능한 메모리가 조각화되고 사용 가능한 영역이 2 개 이상있을 수 있으므로 모든 구성이 손상됩니다.
Alexei Kaigorodov

팝핑은 실제로 문제이지만, Alexei의 구성은 Dmitri가 주석에서 요청한 문제의 버전에 대한 상한을 제공합니다. 모든 팝 전에 모든 푸시가 필요하면 어떻게됩니까? 이 경우 O (log N)보다 나은 것이 가능한지 궁금합니다.
user1020406
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.