Welcome to Subscribe On Youtube

Formatted question description: https://leetcode.ca/all/716.html

716. Max Stack

Level

Easy

Description

Design a max stack that supports push, pop, top, peekMax and popMax.

  1. push(x) – Push element x onto stack.
  2. pop() – Remove the element on top of the stack and return it.
  3. top() – Get the element on the top.
  4. peekMax() – Retrieve the maximum element in the stack.
  5. popMax() – Retrieve the maximum element in the stack, and remove it. If you find more than one maximum elements, only remove the top-most one.

Example 1:

MaxStack stack = new MaxStack();
stack.push(5); 
stack.push(1);
stack.push(5);
stack.top(); -> 5
stack.popMax(); -> 5
stack.top(); -> 1
stack.peekMax(); -> 5
stack.pop(); -> 1
stack.top(); -> 5

Note:

  1. -1e7 <= x <= 1e7
  2. Number of operations won’t exceed 10000.
  3. The last four operations won’t be called when stack is empty.

Solution

A stack supports push, pop, and top already, so only the last two operations need to be implemented. Use two stacks.

  • One stack works as the normal stack,
  • and the other stack which is called the maximum stack stores the maximum element so far.

Both stacks are initialized in the constructor. The other three functions should be modified as well.

  1. The push() function. Push the element into the normal stack, and for the maximum stack, if the maximum stack is empty, then simply push the element into the maximum stack, otherwise push the maximum element between the current element and the element at the top of the maximum stack.

  2. The pop() function. Simply pop both the normal stack and the maximum stack, and return the element popped from the normal stack.

  3. The top() function. Simply return the top element of the normal stack.

  4. The peekMax() function. Simply return the top element of the maximum stack. The reason why this works is that, each time the push function is called, the element pushed into the maximum stack is guaranteed to be the maximum element so far, so at any time, the top element of the maximum stack is the maximum element among all the elements pushed.

  5. The popMax() function. This is a highly complex function that requires careful handling. Since the maximum element may not always be at the top of the normal stack, it may be necessary to first pop some elements from the normal stack in order to locate it. The top element of the normal stack is considered the maximum only if it is identical to the top element of the maximum stack. Once the maximum element has been popped, any other elements that were previously removed from the normal stack must be re-added. To accomplish this, a new stack is used to store all the popped elements until the maximum element is identified. Once the maximum element has been popped and retrieved, each element in the new stack must be pushed back onto the normal stack, to ensure that both the normal stack and the maximum stack contain the correct values.

  • class MaxStack {
        Stack<Integer> stack;
        Stack<Integer> maxStack;
    
        /** initialize your data structure here. */
        public MaxStack() {
            stack = new Stack<Integer>();
            maxStack = new Stack<Integer>();
        }
        
        public void push(int x) {
            stack.push(x);
            if (maxStack.isEmpty())
                maxStack.push(x);
            else {
                int prev = maxStack.peek();
                x = Math.max(x, prev);
                maxStack.push(x);
            }
        }
        
        public int pop() {
            int element = stack.pop();
            maxStack.pop();
            return element;
        }
        
        public int top() {
            return stack.peek();
        }
        
        public int peekMax() {
            return maxStack.peek();
        }
        
        public int popMax() {
            int max = maxStack.peek();
            Stack<Integer> tempStack = new Stack<Integer>();
            while (stack.peek() != max) {
                tempStack.push(stack.pop());
                maxStack.pop();
            }
            stack.pop();
            maxStack.pop();
            while (!tempStack.isEmpty())
                push(tempStack.pop());
            return max;
        }
    }
    
    /**
     * Your MaxStack object will be instantiated and called as such:
     * MaxStack obj = new MaxStack();
     * obj.push(x);
     * int param_2 = obj.pop();
     * int param_3 = obj.top();
     * int param_4 = obj.peekMax();
     * int param_5 = obj.popMax();
     */
    
    ############
    
    class Node {
        public int val;
        public Node prev, next;
    
        public Node() {
        }
    
        public Node(int val) {
            this.val = val;
        }
    }
    
    class DoubleLinkedList {
        private final Node head = new Node();
        private final Node tail = new Node();
    
        public DoubleLinkedList() {
            head.next = tail;
            tail.prev = head;
        }
    
        public Node append(int val) {
            Node node = new Node(val);
            node.next = tail;
            node.prev = tail.prev;
            tail.prev = node;
            node.prev.next = node;
            return node;
        }
    
        public static Node remove(Node node) {
            node.prev.next = node.next;
            node.next.prev = node.prev;
            return node;
        }
    
        public Node pop() {
            return remove(tail.prev);
        }
    
        public int peek() {
            return tail.prev.val;
        }
    }
    
    class MaxStack {
        private DoubleLinkedList stk = new DoubleLinkedList();
        private TreeMap<Integer, List<Node>> tm = new TreeMap<>();
    
        public MaxStack() {
        }
    
        public void push(int x) {
            Node node = stk.append(x);
            tm.computeIfAbsent(x, k -> new ArrayList<>()).add(node);
        }
    
        public int pop() {
            Node node = stk.pop();
            List<Node> nodes = tm.get(node.val);
            int x = nodes.remove(nodes.size() - 1).val;
            if (nodes.isEmpty()) {
                tm.remove(node.val);
            }
            return x;
        }
    
        public int top() {
            return stk.peek();
        }
    
        public int peekMax() {
            return tm.lastKey();
        }
    
        public int popMax() {
            int x = peekMax();
            List<Node> nodes = tm.get(x);
            Node node = nodes.remove(nodes.size() - 1);
            if (nodes.isEmpty()) {
                tm.remove(x);
            }
            DoubleLinkedList.remove(node);
            return x;
        }
    }
    
    /**
     * Your MaxStack object will be instantiated and called as such:
     * MaxStack obj = new MaxStack();
     * obj.push(x);
     * int param_2 = obj.pop();
     * int param_3 = obj.top();
     * int param_4 = obj.peekMax();
     * int param_5 = obj.popMax();
     */
    
  • // OJ: https://leetcode.com/problems/max-stack/
    // Time:
    //      MaxStack, top, peekMax: O(1)
    //      push: log(N)
    //      pop, popMax: O(logN) amortized
    // Space: O(N)
    class MaxStack {
        map<int, vector<int>> m;
        vector<int> v;
        void pop(int n) {
            int i = m[n].back();
            v[i] = INT_MIN;
            m[n].pop_back();
            if (m[n].empty()) m.erase(n);
            while (v.size() && v.back() == INT_MIN) v.pop_back();
        }
    public:
        MaxStack() {}
        void push(int x) {
            m[x].push_back(v.size());
            v.push_back(x);
        }
        int pop() {
            int n = v.back();
            pop(n);
            return n;
        }
        int top() {
            return v.back();
        }
        int peekMax() {
            return m.rbegin()->first;
        }
        int popMax() {
            int n = peekMax();
            pop(n);
            return n;
        }
    };
    
  • class MaxStack(object):
    
        def __init__(self):
            """
            initialize your data structure here.
            """
            self.stack = []
            self.max_stack = []
    
        def push(self, x):
            """
            :type x: int
            :rtype: void
            """
            self.stack.append(x)
            self.max_stack.append(max(x, self.max_stack[-1]) if self.max_stack else x)
    
        def pop(self):
            """
            :rtype: int
            """
            if len(self.stack) != 0:
                self.max_stack.pop(-1)
                return self.stack.pop(-1)
    
        def top(self):
            """
            :rtype: int
            """
            return self.stack[-1]
    
        def peekMax(self):
            """
            :rtype: int
            """
            if len(self.max_stack) != 0:
                return self.max_stack[-1]
    
        def popMax(self):
            """
            :rtype: int
            """
            val = self.peekMax()
            buff = []
            while self.top() != val:
                buff.append(self.pop())
            self.pop()
            while len(buff) != 0:
                self.push(buff.pop(-1))
            return val
    
    ###########
    
    from sortedcontainers import SortedList
    
    class Node:
        def __init__(self, val=0):
            self.val = val
            self.prev: Union[Node, None] = None
            self.next: Union[Node, None] = None
    
    
    class DoubleLinkedList:
        def __init__(self):
            self.head = Node()
            self.tail = Node()
            self.head.next = self.tail
            self.tail.prev = self.head
    
        def append(self, val) -> Node:
            node = Node(val)
            node.next = self.tail
            node.prev = self.tail.prev
            self.tail.prev = node
            node.prev.next = node
            return node
    
        @staticmethod
        def remove(node) -> Node:
            node.prev.next = node.next
            node.next.prev = node.prev
            return node
    
        def pop(self) -> Node:
            return self.remove(self.tail.prev)
    
        def peek(self):
            return self.tail.prev.val
    
    
    class MaxStack:
        def __init__(self):
            self.stk = DoubleLinkedList()
            self.sl = SortedList(key=lambda x: x.val)
    
        def push(self, x: int) -> None:
            node = self.stk.append(x)
            self.sl.add(node)
    
        def pop(self) -> int:
            node = self.stk.pop()
            self.sl.remove(node)
            return node.val
    
        def top(self) -> int:
            return self.stk.peek()
    
        def peekMax(self) -> int:
            return self.sl[-1].val
    
        def popMax(self) -> int:
            node = self.sl.pop()
            DoubleLinkedList.remove(node)
            return node.val
    
    
    # Your MaxStack object will be instantiated and called as such:
    # obj = MaxStack()
    # obj.push(x)
    # param_2 = obj.pop()
    # param_3 = obj.top()
    # param_4 = obj.peekMax()
    # param_5 = obj.popMax()
    
    

All Problems

All Solutions