# [未完成] 使用Queue實現Stack的3種方法 (Leetcode 225) > 寫每日一題的時候發現這題好像在哪間學校的考古題寫過,感覺蠻有機會考出來,就把所有思路都記錄下來,萬一考出來了? `[112交大]` > 考試時可能還要注意 $isFull()$ 的情況。 [ToC] | LeetCode | 力扣 | | -------- | -------- | | [225. Implement Stack using Queues](https://leetcode.com/problems/implement-stack-using-queues/) | [225. 用队列实现栈](https://leetcode.cn/problems/implement-stack-using-queues/) ## Python的deque套件簡介 依照題目的要求,能使用那些函數,且python中是如何調用的 $back()$ ? -> X [未完成] ## Method 1. 使用兩個queue,在 push() 時調整 - 目的為**使queue1維持stack的性質** (即queue1的第1個元素為stack上最頂端的元素,以此類推),queue2用來在調整時暫存queue1的元素 - 時間複雜度: - $push()$: $O(n)$ - $pop()$: $O(1)$ - $top()$: $O(1)$ - $empty()$: $O(1)$ - 在上述的前提下,可以發現在stack的4個操作裡面,只有 $push()$ 會破壞這個性質,因此我們要在 $push()$ 的時候做調整。 - 在 $push()$ 時,因為queue1本身就具stack的性質,為了繼續維持stack性質,可以先先把新的元素push到queue2,這樣新的元素在queue2中就會是stack最頂層的元素。 - 之後再把原本queue1內的元素依次加入queue2中 (pop出來後push進queue2),queue2就會維持stack的性質,最後再把queue1和queue2兩者交換,讓queue1繼續維持stack的性質就好。 ```python= from collections import deque class MyStack1: def __init__(self): self.queue1 = deque() self.queue2 = deque() def push(self, x: int) -> None: """ 因為queue1要保持stack的性質,所以要把queue1的元素都移到queue2 那麼queue2的元素就會維持stack的性質,最後再把兩者交換,讓queue1維持stack的性質 """ self.queue2.append(x) while self.queue1: self.queue2.append(self.queue1.popleft()) self.queue1, self.queue2 = self.queue2, self.queue1 def pop(self) -> int: """ 在某些語言中的pop()可能不能處理size為0的情況,考試時要注意 """ return self.queue1.popleft() if self.queue1 else None def top(self) -> int: """ Python的deque沒有top(),直接取[0]就好,另外和pop()相同,在某些語言中的top()可能不能處理size為0的情況,考試時要注意 """ return self.queue1[0] if self.queue1 else None def empty(self) -> bool: return not self.queue1 ``` ## Method 2. 使用兩個queue,在 pop() 時調整 - 目的為**使queue1還是維持queue的性質**,queue2同樣用來在調整時暫存queue1的元素 - 時間複雜度: - $push()$: $O(1)$ - $pop()$: $O(n)$ - $top()$: $O(n)$ - $empty()$: $O(1)$ - 在上述的前提下,可以發現在stack的4個操作裡面,其實都不會破壞這個性質。 - 但在 $pop()$ 時因為我們不能直接取出和刪除最後一個元素,所以我們要利用暫存用的queue2,先對queue1做n-1次pop,同時把元素push到queue2後,再對queue1做1次pop把最後一個元素pop出來,這個元素就是stack頂端的元素。最後再把兩個queue交換,讓queue1維持原本的性質。 - 在做 $top()$ 時我們同樣不能直接取出最後一個元素,但我們可以利用已經寫好的 $pop()$ ,把頂端的元素pop出來,再把它push回去就好。 - 有些題解在取 $top()$ 時的的方法是用了 $back()$ ,但是這樣就不是queue了,不符合題目要求。 ```python= class MyStack2: def __init__(self): self.queue1 = deque() self.queue2 = deque() def push(self, x: int) -> None: self.queue1.append(x) def pop(self) -> int: if not self.queue1: return None size = len(self.queue1) while size > 1: self.queue2.append(self.queue1.popleft()) size -= 1 self.queue1, self.queue2 = self.queue2, self.queue1 return self.queue2.popleft() def top(self) -> int: """ 這裡可以用上述的pop()方法把top的元素pop出來,再把它push回去就好了 """ if not self.queue1: return None top = self.pop() self.push(top) return top def empty(self) -> bool: return not self.queue1 ``` ## Method 3. 使用一個queue,在 pop() 時調整 - 和方法2.類似,但是不用兩個queue,而是只用一個queue就能完成 - 使queue1還是維持queue的性質,但**不用使用另外一個queue2暫存queue1的元素,直接push回queue1即可** - 時間複雜度: - $push()$: $O(1)$ - $pop()$: $O(n)$ - $top()$: $O(n)$ - $empty()$: $O(1)$ - 概念和方法2.基本相同,因此不再贅述。 ```python= class MyStack3: def __init__(self): self.queue = deque() def push(self, x: int) -> None: self.queue.append(x) def pop(self) -> int: if not self.queue: return None size = len(self.queue) while size > 1: self.queue.append(self.queue.popleft()) size -= 1 return self.queue.popleft() def top(self) -> int: """ 這裡可以用上述的pop()方法把top的元素pop出來,再把它push回去就好了 """ if not self.queue: return None top = self.pop() self.push(top) return top def empty(self) -> bool: return not self.queue class MyStack(MyStack3): pass ```