아래의 대답은 '속임수'입니다. 작업 간 공간을 사용하지 않지만 작업 자체는 이상의 공간을 사용할 수 있습니다 . 이 스레드의 다른 곳에서이 문제가없는 답변을 참조하십시오.O(1)
정확한 질문에 대한 답변이 없지만 O 에서 작동하는 알고리즘을 찾았습니다 ( √O(n)대신에 n )시간. 나는 증거가 없지만 이것이 빡빡하다고 생각합니다. 어쨌든, 알고리즘은O(n)의 하한을 증명하려고 시도하는것은 쓸데없는 일이므로 귀하의 질문에 대답하는 데 도움이 될 수 있습니다.O(n−−√)O(n)O(n)
나는 두 개의 알고리즘을 제시하는데, 첫 번째는 Pop에 대한 실행 시간을 가진 간단한 알고리즘이고 두 번째 알고리즘 은 O ( √O(n)Pop의 실행 시간 첫 번째는 주로 단순성 때문에 두 번째 것이 이해하기 쉽도록 설명합니다.O(n−−√)
더 자세하게 설명하자면, 첫 번째는 추가 공간을 사용하지 않고 최악의 경우 (및 상각) 푸시와 O ( n ) 최악의 경우 (및 상각) 팝을 갖지만 최악의 경우 항상 트리거되는 것은 아닙니다. 두 대기열 이상의 추가 공간을 사용하지 않기 때문에 Ross Snider가 제공하는 솔루션보다 약간 더 낫습니다.O(1)O(n)
두 번째는 단일 정수 필드 (따라서 여분의 공간)를 사용하고 O ( 1 ) 최악의 경우 (및 상각) 푸시 및 O ( √O(1)O(1)팝을 상각했다. 따라서 '간단한'접근 방식보다 실행 시간이 훨씬 뛰어나지 만 추가 공간을 사용합니다.O(n−−√)
첫 번째 알고리즘
우리는 queue 와 queue s e c o n d 의 두 개의 대기열을 가지고 있습니다 . F 나 r에 들 t는 동안, 우리 '푸시 큐'것 S E C O N에서 D가 이미 '스택 주문에 대기열 될 것이다.firstsecondfirstsecond
- 단순히 상 매개 변수가 대기 상태에서 행해진 다 밀어 .first
- 팝핑은 다음과 같이 수행됩니다. 경우 , 우리는 단순히 디큐 비어 의 E C O N에서 D , 그 결과를 반환한다. 그렇지 않으면, 우리는 역방향 f를 난 r에 S t , 모든 추가 의 예 C O N의 D를 로 f를 난 r에 S를 t 와 스왑 f를 난 r에 S를 t 와 S의 E C의 입출력 N 개의 D를 . 그런 다음 s e c ofirstsecondfirstsecondfirstfirstsecond 및 대기열에서 제외 된 결과를 반환합니다.second
첫 번째 알고리즘의 C # 코드
C #을 본 적이 없어도 읽을 수 있어야합니다. 제네릭이 무엇인지 모르는 경우 문자열 스택에 대해 'T'의 모든 인스턴스를 'string'으로 바꾸십시오.
public class Stack<T> {
private Queue<T> first = new Queue<T>();
private Queue<T> second = new Queue<T>();
public void Push(T value) {
first.Enqueue(value);
}
public T Pop() {
if (first.Count == 0) {
if (second.Count > 0)
return second.Dequeue();
else
throw new InvalidOperationException("Empty stack.");
} else {
int nrOfItemsInFirst = first.Count;
T[] reverser = new T[nrOfItemsInFirst];
// Reverse first
for (int i = 0; i < nrOfItemsInFirst; i++)
reverser[i] = first.Dequeue();
for (int i = nrOfItemsInFirst - 1; i >= 0; i--)
first.Enqueue(reverser[i]);
// Append second to first
while (second.Count > 0)
first.Enqueue(second.Dequeue());
// Swap first and second
Queue<T> temp = first; first = second; second = temp;
return second.Dequeue();
}
}
}
분석
분명히 Push는 시간 안에 작동합니다 . 팝 안에 모든 터치 수 f를 난 r에 S를 t 와 S의 E C의 입출력 N 개의 D를 회 일정량 그래서 우리가 O ( N를 ) 최악의 경우. 알고리즘은 예를 들어 n 개의 요소를 스택에 푸시 한 다음 단일 푸시와 단일 팝 작업을 연속으로 반복 수행하는 경우이 동작을 나타냅니다 .O(1)firstsecondO(n)n
두 번째 알고리즘
우리는 queue 와 queue s e c o n d 의 두 개의 대기열을 가지고 있습니다 . F 나 r에 들 t는 동안, 우리 '푸시 큐'것 S E C O N에서 D가 이미 '스택 주문에 대기열 될 것이다.firstsecondfirstsecond
이것은 우리가 바로 '셔플'의 내용에 있지 않은 제 알고리즘의 적응 버전 에 S를 E C의 입출력 N 개의 D를 . 경우 대신 f를 난 r에 들 t는 비교 소자 충분히 적은 포함 S E C O N에서 D (원소 개수, 즉 제곱근 들에 전자 C O의 n 개의 D를 ), 우리는 재구성 f를 난 r에 S t 스택 순서로 병합하지 마십시오.firstsecondfirstsecondsecondfirst .second
- 푸시 아직도 단순히 상 매개 변수가 대기 상태에서 행해진 다 .first
- 팝핑은 다음과 같이 수행됩니다. 경우 , 우리는 단순히 디큐 비어 의 E C O N에서 D , 그 결과를 반환한다. 그렇지 않으면, 우리의 내용을 재구성 f를 내가 r에 S의 t을 그들이 스택 순서에 있도록. 경우 | f i r s t | < √firsts e c o n d에프난 r에 S t우리는 단순히first를 대기열에서 빼고결과를 반환합니다. 그렇지 않으면, 우리는 추가S의EC의입출력N의D를로F나r에S의t를스왑을f를난r에S를t와S의EC의입출력N의D, 디큐SECON에서D를하고 그 결과를 리턴한다.| 에프나는 r에 S의 t을 | < | s e c o n d|−−−−−−−√에프난 r에 S ts e c o n d에프난 r에 S t에프난 r에 S ts e c o n ds e c o n d
첫 번째 알고리즘의 C # 코드
C #을 본 적이 없어도 읽을 수 있어야합니다. 제네릭이 무엇인지 모르는 경우 문자열 스택에 대해 'T'의 모든 인스턴스를 'string'으로 바꾸십시오.
public class Stack<T> {
private Queue<T> first = new Queue<T>();
private Queue<T> second = new Queue<T>();
int unsortedPart = 0;
public void Push(T value) {
unsortedPart++;
first.Enqueue(value);
}
public T Pop() {
if (first.Count == 0) {
if (second.Count > 0)
return second.Dequeue();
else
throw new InvalidOperationException("Empty stack.");
} else {
int nrOfItemsInFirst = first.Count;
T[] reverser = new T[nrOfItemsInFirst];
for (int i = nrOfItemsInFirst - unsortedPart - 1; i >= 0; i--)
reverser[i] = first.Dequeue();
for (int i = nrOfItemsInFirst - unsortedPart; i < nrOfItemsInFirst; i++)
reverser[i] = first.Dequeue();
for (int i = nrOfItemsInFirst - 1; i >= 0; i--)
first.Enqueue(reverser[i]);
unsortedPart = 0;
if (first.Count * first.Count < second.Count)
return first.Dequeue();
else {
while (second.Count > 0)
first.Enqueue(second.Dequeue());
Queue<T> temp = first; first = second; second = temp;
return second.Dequeue();
}
}
}
}
분석
분명히 Push는 시간 안에 작동합니다 .O(1)
팝은 O 에서 작동합니다 ( √상각 시간. 두 가지 경우가 있습니다 : if| first| < √O(n−−√)다음 셔플 우리가f를난r에S를t를스택의 순서로O(|f를난r에St|)=O(√|first|<|second|−−−−−−−√first시간. 경우| first| ≥ √O(|first|)=O(n−−√), 우리는 적어도√를가지고 있어야합니다|first|≥|second|−−−−−−−√ 은 푸시를 요구합니다. 따라서 우리는 √ 마다이 사건을 칠 수 있습니다n−−√ 누르고 팝업 호출. 이 경우 실제 실행 시간은O(n)이므로 상각 된 시간은O( n)입니다.n−−√O(n).O(nn√)=O(n−−√)
최종 메모
Pop an O ( √ 를 만드는 비용으로 추가 변수를 제거하는 것이 가능합니다 ( √동작 팝 재구성 가짐으로써f를난r에St대신 푸시 모든 작업을 가지는 모든 호출에.O(n−−√)first