【剑指Offer】个人学习笔记_30_包含min函数的栈

刷题日期:19:2741 星期一2021年4月12日

个人刷题记录,代码收集,来源皆为leetcode

经过多方讨论和请教,现在打算往Java方向发力

主要答题语言为Java

题目:

剑指 Offer 30. 包含min函数的栈

难度简单118

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 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
题目分析

数据结构定义,还是Java,有点懵。

完全没有思路,数据结构基础有点弱。

初始解答:

还需要用到辅助栈。学习方法一

class MinStack {

    /** initialize your data structure here. */
    private Node head; //定义节点

    public MinStack() { //新数据结构

    }

    public void push(int x) { //输入函数

        if (head == null) //分当前链表是否为空
            head = new Node(x, x, null);
        else
            head = new Node(x, Math.min(head.min, x), head); //与现有最小值比较
    }

    public void pop() { //出栈

        head = head.next;
    }

    public int top() { //返回栈顶元素

        return head.val;
    }

    public int min() { //返回辅助栈的最小值

        return head.min;
    }

    private class Node { //节点定义

        int val;  //数据
        int min;  //最小值
        Node next; //下一个节点

        public Node(int val, int min, Node next) { //声明

            this.val = val;
            this.min = min;
            this.next = next;
        }
    }
}

/**
 * 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();
 */

执行结果:通过

显示详情

执行用时:22 ms, 在所有 Java 提交中击败了91.72%的用户

内存消耗:39.9 MB, 在所有 Java 提交中击败了98.80%的用户

学习K神的代码

class MinStack {
    Stack<Integer> A, B; //用栈实现栈 声明
    /** initialize your data structure here. */
    public MinStack() {
        A = new Stack<>(); //定义两个辅助栈
        B = new Stack<>();
    }
    
    public void push(int x) {
        A.add(x); //A要入
        if (B.empty() || B.peek() >= x) B.add(x); //如果该值小于B顶,则B也入
    }
    
    public void pop() {
        if(A.pop().equals(B.peek())) B.pop(); //如果两个栈顶相等,则B输出
    }
    
    public int top() {
        return A.peek(); //返回A顶即可
    }
    
    public int min() {
        return B.peek(); //B顶即当前最小值
    }
}

/**
 * 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();
 */

效率也很高 执行结果:通过

显示详情

执行用时:22 ms, 在所有 Java 提交中击败了91.72%的用户

内存消耗:40 MB, 在所有 Java 提交中击败了93.84%的用户

学习他人:

方法一:

宝石L1 2020-02-28

Java题解 简单明了

让我们实现栈,我们就手写个链表就好啦,每个节点加一个额外属性:当前最小值。

    private Node head;

    public MinStack() {

    }

    public void push(int x) {

        if (head == null)
            head = new Node(x, x, null);
        else
            head = new Node(x, Math.min(head.min, x), head);
    }

    public void pop() {

        head = head.next;
    }

    public int top() {

        return head.val;
    }

    public int min() {

        return head.min;
    }

    private class Node {

        int val;
        int min;
        Node next;

        public Node(int val, int min, Node next) {

            this.val = val;
            this.min = min;
            this.next = next;
        }
    }

方法二:

小牧神 1 天前

API不熟练,难受啊🐎飞~

class MinStack {
    Deque<Integer> stack;
    Deque<Integer> help;   
    /** initialize your data structure here. */
    public MinStack() {
        stack = new ArrayDeque<>();
        help = new ArrayDeque<>();
    }
    
    public void push(int x) {
        stack.push(x);
        //这步处理实在是秒~
        if(help.isEmpty() || x <= help.peek()) help.push(x);
    }
    
    public void pop() {
        int x = stack.pop();
        if(x == help.peek()) help.pop();    
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int min() {
        return help.peek();
    }
}

方法三:


bupt_mzz

2021-02-27

执行用时: 22 ms , 在所有 Java 提交中击败了 89.53% 的用户

直接一个数组,就可以实现,因为调用的次数有限,所以可以先分配一个二倍调用次数大小的数组,其中偶数下标存储之前进栈的最小值,奇数下标存储进栈值,每次每次进栈最小值和进栈值同时添加。

class MinStack {

    /** initialize your data structure here. */
    int[] stack=new int[40000];
    int topIndex=-1;
    public MinStack() {
    }
    public void push(int x) {
        if(topIndex==-1)
        {
            stack[topIndex+1]=x;
        }
        else
        {
            if(x<=stack[topIndex-1])
            {
                stack[1+topIndex]=x;
            }
            else{
                stack[1+topIndex]=stack[topIndex-1];
            }
        }
        stack[2+topIndex]=x;
        topIndex+=2;   
    } 
    public void pop() {
        topIndex-=2;
    }   
    public int top() {
        return stack[topIndex];
    }
    public int min() {
        return stack[topIndex-1];
    }
}

方法四:


擅长捉弄的高木同学imgL1

2020-11-24

效率太低了

class MinStack {
    List<Integer> list;

    /** initialize your data structure here. */
    public MinStack() {
        list = new ArrayList();
    }
    
    public void push(int x) {
        list.add(x);
    }
    
    public void pop() {
        list.remove(list.size()-1);
    }
    
    public int top() {
       return list.get(list.size()-1);
    }
    
    public int min() {
       Integer[] arr = new Integer[list.size()];
       Arrays.sort(list.toArray(arr));
       return list.size() == 0 ? 0 : arr[0];
    }
}

方法五

K神

作者:jyd
链接:https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/solution/mian-shi-ti-30-bao-han-minhan-shu-de-zhan-fu-zhu-z/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Java 代码中,由于 Stack 中存储的是 int 的包装类 Integer ,因此需要使用 equals() 代替 == 来比较值是否相等。

class MinStack {
    Stack<Integer> A, B;
    public MinStack() {
        A = new Stack<>();
        B = new Stack<>();
    }
    public void push(int x) {
        A.add(x);
        if(B.empty() || B.peek() >= x)
            B.add(x);
    }
    public void pop() {
        if(A.pop().equals(B.peek()))
            B.pop();
    }
    public int top() {
        return A.peek();
    }
    public int min() {
        return B.peek();
    }
}

总结

以上就是本题的内容和学习过程了,都需要外部数据结构辅助,应熟练掌握。

欢迎讨论,共同进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值