Implement a last-in-first-out (LIFO) stack using only two queues. The implemented stack should support all the functions of a normal stack (push
, top
, pop
, and empty
).
Implement the MyStack
class:
void push(int x)
Pushes element x to the top of the stack.int pop()
Removes the element on the top of the stack and returns it.int top()
Returns the element on the top of the stack.boolean empty()
Returns true
if the stack is empty, false
otherwise.Notes:
push to back
, peek/pop from front
, size
and is empty
operations are valid.Example 1:
Input [ "MyStack ", "push ", "push ", "top ", "pop ", "empty "] [[], [1], [2], [], [], []] Output [null, null, null, 2, 2, false]
Explanation MyStack myStack = new MyStack(); myStack.push(1); myStack.push(2); myStack.top(); // return 2 myStack.pop(); // return 2 myStack.empty(); // return False
Constraints:
1 <= x <= 9
100
calls will be made to push
, pop
, top
, and empty
.pop
and top
are valid.Follow-up: Can you implement the stack using only one queue?
program main
! This program implements a last-in-first-out (LIFO) stack using only two queues.
implicit none
type :: MyStack
private
integer, allocatable :: q1(:), q2(:)
integer :: size
contains
procedure :: push => push_impl
procedure :: pop => pop_impl
procedure :: top => top_impl
procedure :: empty => empty_impl
end type MyStack
interface MyStack
module procedure constructor
end interface MyStack
contains
function constructor() result(stack)
type(MyStack) :: stack
allocate(stack%q1(0))
allocate(stack%q2(0))
stack%size = 0
end function constructor
subroutine push_impl(this, x)
class(MyStack), intent(inout) :: this
integer, value :: x
if (allocated(this%q1)) then
call move_alloc(this%q1, this%q2)
else
allocate(this%q1(0))
end if
allocate(this%q1(this%size + 1))
this%q1(this%size + 1) = x
this%size = this%size + 1
end subroutine push_impl
function pop_impl(this) result(x)
class(MyStack), intent(inout) :: this
integer :: x
if (.not. allocated(this%q1)) then
error stop 'Error: pop called on empty stack.'
end if
x = this%q1(this%size)
this%size = this%size - 1
if (this%size == 0) then
deallocate(this%q1)
if (allocated(this%q2)) then
call move_alloc(this%q2, this%q1)
end if
end if
end function pop_impl
function top_impl(this) result(x)
class(MyStack), intent(in) :: this
integer :: x
if (.not. allocated(this%q1)) then
error stop 'Error: top called on empty stack.'
end if
x = this%q1(this%size)
end function top_impl
logical function empty_impl(this)
class(MyStack), intent(in) :: this
empty_impl = .not. allocated(this%q1)
end function empty_impl
end program main
temp.f95:6:15: 6 | private | 1 Error: PRIVATE statement at (1) is only allowed in the specification part of a module temp.f95:22:4: 22 | function constructor() result(stack) | 1 Error: INTERNAL-PROC procedure at (1) is already declared as MODULE-PROC procedure temp.f95:13:17: 13 | 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 :: pop => pop_impl | 1 Error: ‘pop_impl’ must be a module procedure or an external procedure with an explicit interface at (1) temp.f95:10:17: 10 | 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:12:17: 12 | procedure :: top => top_impl | 1 Error: ‘top_impl’ must be a module procedure or an external procedure with an explicit interface at (1)
module MyStack
implicit none
private
type :: MyStack_t
integer :: size = 0
integer, allocatable :: queue(:)
end type MyStack_t
interface MyStack
module procedure constructor
end interface MyStack
contains
function constructor() result(this)
type(MyStack_t) :: this
allocate(this%queue(0))
end function constructor
subroutine push(this, x)
class(MyStack_t), intent(inout) :: this
integer, intent(in) :: x
this%size = this%size + 1
allocate(this%queue(this%size))
this%queue(this%size) = x
end subroutine push
function top(this) result(x)
class(MyStack_t), intent(in) :: this
integer :: x
x = this%queue(this%size)
end function top
function pop(this) result(x)
class(MyStack_t), intent(inout) :: this
integer :: x
x = this%queue(this%size)
this%size = this%size - 1
deallocate(this%queue(this%size + 1))
end function pop
function empty(this) result(x)
class(MyStack_t), intent(in) :: this
logical :: x
x = this%size == 0
end function empty
end module MyStack
program main
use MyStack
implicit none
type(MyStack_t) :: stack
integer :: x
! Test case 1:
call stack%push(1)
call stack%push(2)
x = stack%top()
write (*,*) x
x = stack%pop()
write (*,*) x
x = stack%empty()
write (*,*) x
! Test case 2:
call stack%push(3)
call stack%push(4)
x = stack%top()
write (*,*) x
x = stack%pop()
write (*,*) x
x = stack%empty()
write (*,*) x
! Test case 3:
call stack%push(5)
call stack%push(6)
x = stack%top()
write (*,*) x
x = stack%pop()
write (*,*) x
x = stack%empty()
write (*,*) x
end program main
temp.f95:9:21: 9 | interface MyStack | 1 Error: MODULE attribute of ‘mystack’ conflicts with PROCEDURE attribute at (1) temp.f95:10:25: 10 | module procedure constructor | 1 Error: MODULE PROCEDURE at (1) must be in a generic module interface temp.f95:11:7: 11 | end interface MyStack | 1 Error: Expecting END MODULE statement at (1) temp.f95:43:19: 43 | deallocate(this%queue(this%size + 1)) | 1 Error: Allocate-object at (1) must be ALLOCATABLE or a POINTER temp.f95:55:9: 55 | use MyStack | 1 Fatal Error: Cannot open module file ‘mystack.mod’ for reading at (1): No such file or directory compilation terminated.
from collections import deque
class MyStack:
def __init__(self):
self.q1 = deque()
self.q2 = deque()
def push(self, x: int) -> None:
self.q2.append(x)
while self.q1:
self.q2.append(self.q1.popleft())
self.q1, self.q2 = self.q2, self.q1
def pop(self) -> int:
return self.q1.popleft()
def top(self) -> int:
return self.q1[0]
def empty(self) -> bool:
return not self.q1
We have two queues q1 and q2, where we will store the elements. For every push operation, we first push the new element into q2, then move all the elements in the q1 to q2, and then swap both queues. The pop and top operations will always operate on q1, which maintains the elements in the reverse order, simulating the LIFO order of a stack. The empty operation simply checks if q1 is empty.
The time complexity for push is O(n), while the time complexities for top, pop, and empty are O(1).
#include <queue>
class MyStack {
public:
std::queue<int> q1, q2;
void push(int x) {
q2.push(x);
while (!q1.empty()) {
q2.push(q1.front());
q1.pop();
}
std::swap(q1, q2);
}
int pop() {
int top = q1.front();
q1.pop();
return top;
}
int top() {
return q1.front();
}
bool empty() {
return q1.empty();
}
};
We have two queues q1 and q2, where we will store the elements. For every push operation, we first push the new element into q2, then move all the elements in the q1 to q2, and then swap both queues. The pop and top operations will always operate on q1, which maintains the elements in the reverse order, simulating the LIFO order of a stack. The empty operation simply checks if q1 is empty.
The time complexity for push is O(n), while the time complexities for top, pop, and empty are O(1).