Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal queue (push
, peek
, pop
, and empty
).
Implement the MyQueue
class:
void push(int x)
Pushes element x to the back of the queue.int pop()
Removes the element from the front of the queue and returns it.int peek()
Returns the element at the front of the queue.boolean empty()
Returns true
if the queue is empty, false
otherwise.Notes:
push to top
, peek/pop from top
, size
, and is empty
operations are valid.Example 1:
Input [ "MyQueue ", "push ", "push ", "peek ", "pop ", "empty "] [[], [1], [2], [], [], []] Output [null, null, null, 1, 1, false]
Explanation MyQueue myQueue = new MyQueue(); myQueue.push(1); // queue is: [1] myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) myQueue.peek(); // return 1 myQueue.pop(); // return 1, queue is [2] myQueue.empty(); // return false
Constraints:
1 <= x <= 9
100
calls will be made to push
, pop
, peek
, and empty
.pop
and peek
are valid.Follow-up: Can you implement the queue such that each operation is amortized O(1)
time complexity? In other words, performing n
operations will take overall O(n)
time even if one of those operations may take longer.
program main
implicit none
type :: MyQueue
private
integer, allocatable :: stack(:)
integer :: size = 0
contains
procedure :: push => push_impl
procedure :: pop => pop_impl
procedure :: peek => peek_impl
procedure :: empty => empty_impl
end type MyQueue
interface MyQueue
module procedure constructor
end interface MyQueue
contains
function constructor() result(queue)
type(MyQueue) :: queue
allocate(queue%stack(0))
end function constructor
subroutine push_impl(queue, x)
class(MyQueue), intent(inout) :: queue
integer, value :: x
queue%size = queue%size + 1
allocate(queue%stack(queue%size))
queue%stack(queue%size) = x
end subroutine push_impl
function pop_impl(queue) result(x)
class(MyQueue), intent(inout) :: queue
integer :: x
if (queue%empty()) then
error stop 'cannot pop from an empty queue'
end if
x = queue%stack(queue%size)
deallocate(queue%stack(queue%size))
queue%size = queue%size - 1
end function pop_impl
function peek_impl(queue) result(x)
class(MyQueue), intent(in) :: queue
integer :: x
if (queue%empty()) then
error stop 'cannot peek from an empty queue'
end if
x = queue%stack(queue%size)
end function peek_impl
logical function empty_impl(queue) result(empty)
class(MyQueue), intent(in) :: queue
empty = queue%size == 0
end function empty_impl
end program main
temp.f95:5:15: 5 | private | 1 Error: PRIVATE statement at (1) is only allowed in the specification part of a module temp.f95:21:4: 21 | function constructor() result(queue) | 1 Error: INTERNAL-PROC procedure at (1) is already declared as MODULE-PROC procedure temp.f95:12:17: 12 | procedure :: empty => empty_impl | 1 Error: ‘empty_impl’ must be a module procedure or an external procedure with an explicit interface at (1) temp.f95:11:17: 11 | procedure :: peek => peek_impl | 1 Error: ‘peek_impl’ must be a module procedure or an external procedure with an explicit interface at (1) temp.f95:10:17: 10 | procedure :: pop => pop_impl | 1 Error: ‘pop_impl’ must be a module procedure or an external procedure with an explicit interface at (1) temp.f95:9:17: 9 | procedure :: push => push_impl | 1 Error: ‘push_impl’ must be a module procedure or an external procedure with an explicit interface at (1) temp.f95:53:12: 53 | if (queue%empty()) then | 1 Error: ‘empty’ at (1) should be a FUNCTION temp.f95:40:12: 40 | if (queue%empty()) then | 1 Error: ‘empty’ at (1) should be a FUNCTION temp.f95:45:19: 45 | deallocate(queue%stack(queue%size)) | 1 Error: Allocate-object at (1) must be ALLOCATABLE or a POINTER
module MyQueue
! Declare the stacks used to implement the queue
integer :: stack1(100), stack2(100)
integer :: top1, top2
! Declare the functions of the queue
contains
! Push an element to the back of the queue
subroutine push(x)
integer, intent(in) :: x
! If the first stack is empty, push the element to the first stack
if (top1 == 0) then
top1 = 1
stack1(top1) = x
else
! If the first stack is not empty, push the element to the second stack
top2 = top2 + 1
stack2(top2) = x
end if
end subroutine push
! Pop an element from the front of the queue
function pop() result(x)
integer :: x
! If the first stack is empty, pop the element from the second stack
if (top1 == 0) then
top2 = top2 - 1
x = stack2(top2 + 1)
else
! If the first stack is not empty, pop the element from the first stack
top1 = top1 - 1
x = stack1(top1 + 1)
end if
end function pop
! Peek at the element at the front of the queue
function peek() result(x)
integer :: x
! If the first stack is empty, peek at the element from the second stack
if (top1 == 0) then
x = stack2(top2 + 1)
else
! If the first stack is not empty, peek at the element from the first stack
x = stack1(top1 + 1)
end if
end function peek
! Check if the queue is empty
function empty() result(x)
logical :: x
! If both stacks are empty, the queue is empty
if (top1 == 0 .and. top2 == 0) then
x = .true.
else
x = .false.
end if
end function empty
end module MyQueue
! Test the queue with the given examples
program test
use MyQueue
implicit none
! Test case 1: Push and pop
call push(1)
call push(2)
call push(3)
call push(4)
call push(5)
call push(6)
call push(7)
call push(8)
call push(9)
call push(10)
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call pop()
call
temp.f95:188:4: 188 | call | 1 Error: Syntax error in CALL statement at (1) f951: Error: Unexpected end of file in ‘temp.f95’
class MyQueue:
def __init__(self):
self.stack1 = []
self.stack2 = []
def push(self, x: int) -> None:
self.stack1.append(x)
def pop(self) -> int:
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2.pop()
def peek(self) -> int:
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2[-1]
def empty(self) -> bool:
return not self.stack1 and not self.stack2
We can use two stacks(stack1 and stack2) to simulate a queue's functionality. Each time we push an element into the queue, we push it to stack1.
When we need to pop or peek the front element, we check if stack2 is empty; if so, pop all elements from stack1 and push them to stack2. The front element of the queue then would be on the top of the stack2. If stack2 is not empty, just pop or peek the top element of stack2.
To check if the queue is empty, we just need to check if both the stacks are empty.
By doing this, we are maintaining stack2 as the reversed version of stack1, which allows us to access the elements in the correct order for a queue (FIFO).
class MyQueue {
public:
stack<int> stack1, stack2;
MyQueue() {
}
void push(int x) {
stack1.push(x);
}
int pop() {
if (stack2.empty()) {
while (!stack1.empty()) {
stack2.push(stack1.top());
stack1.pop();
}
}
int top_element = stack2.top();
stack2.pop();
return top_element;
}
int peek() {
if (stack2.empty()) {
while (!stack1.empty()) {
stack2.push(stack1.top());
stack1.pop();
}
}
return stack2.top();
}
bool empty() {
return stack1.empty() && stack2.empty();
}
};
We can use two stacks(stack1 and stack2) to simulate a queue's functionality. Each time we push an element into the queue, we push it to stack1.
When we need to pop or peek the front element, we check if stack2 is empty; if so, pop all elements from stack1 and push them to stack2. The front element of the queue then would be on the top of the stack2. If stack2 is not empty, just pop or peek the top element of stack2.
To check if the queue is empty, we just need to check if both the stacks are empty.
By doing this, we are maintaining stack2 as the reversed version of stack1, which allows us to access the elements in the correct order for a queue (FIFO).