美文网首页
30. 包含min函数的栈

30. 包含min函数的栈

作者: 木木与呆呆 | 来源:发表于2022-02-22 10:43 被阅读0次

    链接

    https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/
    难度: #简单

    题目

    定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

    示例:

    MinStack minStack = new MinStack();
    minStack.push(-2);
    minStack.push(0);
    minStack.push(-3);
    minStack.min();   --> 返回 -3.
    minStack.pop();
    minStack.top();   --> 返回 0.
    minStack.min();   --> 返回 -2.
    

    提示:

    1.各函数的调用总次数不超过 20000 次

    代码框架

    class MinStack {
    
     /** initialize your data structure here. */
     public MinStack() {
     }
    
     public void push(int x) {
     }
    
     public void pop() {
     }
    
     public int top() {
     }
    
     public int min() {
     }
    }
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * MinStack obj = new MinStack();
     * obj.push(x);
     * obj.pop();
     * int param_3 = obj.top();
     * int param_4 = obj.min();
     */
    

    题目解析

    该题的难度主要在于调用 min、push 及 pop 的时间复杂度都是 O(1),
    使用栈或者链表都可以保证push和pop的时间复杂度是O(1),
    只要另外找个一个解答思路,
    保证min的时间复杂度是O(1)即可。

    另外解释一下题目中的几个函数,
    push元素入栈,
    pop元素出栈,但没有返回值,
    top查看栈顶元素,
    min返回当前最小的元素。

    解答思路1:
    用Stack来进行堆栈操作,用TreeSet来找到最小值,注意同时记录重复出现的数据。

    解答思路2:
    使用两个栈,主栈用于正常的入栈和出栈操作,
    辅助栈用于记录当前的最小值,注意这个栈中的最小值是和主栈对应的,
    主栈的元素入栈和出栈时,这个最小值是变化的。

    解答思路3:
    使用一个栈,栈中保存的不仅仅是Integer,
    而是一个封装的节点对象,
    该节点保存当前的元素,以及当前的最小值。

    解答思路4:
    使用一个栈,这个栈是用LinkedList模拟出来的,
    为了符合题意,限制性的只能使用其四个方法,
    分别为isEmpty();addLast();getLast();removeLast();
    栈中保存的不仅仅是Integer,
    而是一个封装的节点对象,
    该节点保存当前的元素,以及当前的最小值。

    解答思路5:
    自己实现单向链表来模拟一个栈,
    对元素的入栈和出栈操作都在链表头部即可。
    栈中保存的不仅仅是Integer,
    而是一个封装的节点对象,
    该节点保存当前的元素,以及当前的最小值,
    还有指向下一个节点的指针。
    感觉该解题思路是最符合题意的,
    特别是可以清楚的看出时间复杂度,
    确保调用 min、push 及 pop 的时间复杂度都是 O(1),
    同时空间复杂度为O(n)。

    测试用例

    package edu.yuwen.sowrd.num30.solution;
    
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    
    import edu.yuwen.sowrd.num30.sol5.MinStack;
    
    public class MinStackTest {
    
        @Test
        public void testCase1() {
            MinStack minStack = new MinStack();
            minStack.push(-2);
            minStack.push(0);
            minStack.push(-3);
            int res = minStack.min(); // 返回 -3.
            Assertions.assertEquals(-3, res);
            minStack.pop();
            res = minStack.top(); // 返回 0.
            Assertions.assertEquals(0, res);
            res = minStack.min(); // 返回 -2.
            Assertions.assertEquals(-2, res);
        }
    
        @Test
        public void testCase2() {
            MinStack minStack = new MinStack();
            minStack.push(0);
            minStack.push(1);
            minStack.push(0);
            int res = minStack.min(); // 返回 0.
            Assertions.assertEquals(0, res);
            minStack.pop();
            res = minStack.min(); // 返回 0.
            Assertions.assertEquals(0, res);
        }
    
        @Test
        public void testCase3() {
            MinStack minStack = new MinStack();
            minStack.push(2);
            minStack.push(0);
            minStack.push(3);
            minStack.push(0);
            int res = minStack.min(); // 返回 0.
            Assertions.assertEquals(0, res);
            minStack.pop();
            res = minStack.min(); // 返回 0.
            Assertions.assertEquals(0, res);
            minStack.pop();
            res = minStack.min(); // 返回 0.
            Assertions.assertEquals(0, res);
            minStack.pop();
            res = minStack.min(); // 返回 2.
            Assertions.assertEquals(2, res);
        }
    }
    

    解答1

    package edu.yuwen.sowrd.num30.sol1;
    
    import java.util.Stack;
    import java.util.TreeMap;
    
    public class MinStack {
        // 用Stack来进行堆栈操作
        Stack<Integer> stack;
        // 用TreeSet来找到最小值,同时记录重复数据
        TreeMap<Integer, Integer> treeMap;
    
        public MinStack() {
            stack = new Stack<>();
            treeMap = new TreeMap<>();
        }
    
        public void push(int x) {
            stack.push(x);
            Integer value = treeMap.get(x);
            if (value == null) {
                value = 1;
            } else {
                value++;
            }
            treeMap.put(x, value);
        }
    
        // 弹出栈顶元素
        public void pop() {
            int num = stack.pop();
            Integer value = treeMap.get(num);
            value--;
            if (value == 0) {
                treeMap.remove(num);
            } else {
                treeMap.put(num, value);
            }
        }
    
        // 查看栈顶元素
        public int top() {
            return stack.peek();
        }
    
        public int min() {
            return treeMap.firstKey();
        }
    }
    

    解答2

    package edu.yuwen.sowrd.num30.sol2;
    
    import java.util.Stack;
    
    public class MinStack {
    
        // 主栈和辅助栈
        Stack<Integer> master;
        Stack<Integer> slave;
    
        public MinStack() {
            master = new Stack<>();
            slave = new Stack<>();
        }
    
        public void push(int x) {
            master.push(x);
            // 如果辅助栈为空,则当前元素就是最小值
            if (slave.isEmpty()) {
                slave.push(x);
            }
            // 否则和slave栈顶的最小值比较
            else {
                Integer min = slave.peek();
                // 如果x小于最小值min则插入x,否则插入min
                if (x < min) {
                    slave.push(x);
                } else {
                    slave.push(min);
                }
            }
        }
    
        public void pop() {
            master.pop();
            slave.pop();
        }
    
        public int top() {
            return master.peek();
        }
    
        public int min() {
            return slave.peek();
        }
    }
    

    解答3

    package edu.yuwen.sowrd.num30.sol3;
    
    import java.util.Stack;
    
    public class MinStack {
    
        Stack<Node> stack;
    
        public MinStack() {
            stack = new Stack<>();
        }
    
        public void push(int x) {
            Integer min = null;
            // 堆栈为空,当前元素就是最小值
            if (stack.isEmpty()) {
                min = x;
            }
            // 否则取出上一个节点的最小值进行比较
            else {
                Node pre = stack.peek();
                min = pre.min;
                // 如果当前元素小于最小值min,则更新min的值
                if (x < min) {
                    min = x;
                }
            }
    
            Node item = new Node(x, min);
            stack.push(item);
        }
    
        public void pop() {
            stack.pop();
        }
    
        public int top() {
            return stack.peek().value;
        }
    
        public int min() {
            return stack.peek().min;
        }
    }
    
    class Node {
        // 当前元素
        Integer value;
        // 当前最小值
        Integer min;
    
        Node(Integer value, Integer min) {
            this.value = value;
            this.min = min;
        }
    
    }
    

    解答4

    package edu.yuwen.sowrd.num30.sol4;
    
    import java.util.LinkedList;
    
    public class MinStack {
    
        LinkedList<Node> stack;
    
        public MinStack() {
            stack = new LinkedList<>();
        }
    
        public void push(int x) {
            Integer min = null;
            // 堆栈为空,当前元素就是最小值
            if (stack.isEmpty()) {
                min = x;
            }
            // 否则取出上一个节点的最小值进行比较
            else {
                Node pre = stack.getLast();
                min = pre.min;
                // 如果当前元素小于最小值min,则更新min的值
                if (x < min) {
                    min = x;
                }
            }
    
            Node item = new Node(x, min);
            stack.addLast(item);
        }
    
        public void pop() {
            stack.removeLast();
        }
    
        public int top() {
            return stack.getLast().value;
        }
    
        public int min() {
            return stack.getLast().min;
        }
    }
    
    class Node {
        // 当前元素
        Integer value;
        // 当前最小值
        Integer min;
    
        Node(Integer value, Integer min) {
            this.value = value;
            this.min = min;
        }
    }
    

    解答5 推荐

    package edu.yuwen.sowrd.num30.sol5;
    
    public class MinStack {
    
        Node head;
    
        public MinStack() {
            head = null;
        }
    
        public void push(int x) {
            // 链表为空,则当前元素是最小值
            if (head == null) {
                head = new Node(x, x, null);
                return;
            }
            // 找个链表中的最小值和当前元素比较
            Integer min = head.min;
            if (x < min) {
                min = x;
            }
            // 在表头插入新的节点
            head = new Node(x, min, head);
        }
    
        public void pop() {
            // 去掉表头第一个元素
            head = head.next;
        }
    
        public int top() {
            return head.value;
        }
    
        public int min() {
            return head.min;
        }
    }
    
    class Node {
        // 当前元素
        Integer value;
        // 当前最小值
        Integer min;
        // 下一个节点
        Node next;
    
        Node(Integer value, Integer min, Node next) {
            this.value = value;
            this.min = min;
            this.next = next;
        }
    }
    

    相关文章

      网友评论

          本文标题:30. 包含min函数的栈

          本文链接:https://www.haomeiwen.com/subject/ezfglrtx.html