【剑指offer】包含min函数的栈(Java解答,单栈和双栈解法)

题目描述

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

分析
本题的时间复杂度已经确定,那么算法优化就只能从空间复杂度下手,一般来说采用辅助栈保存当前最小值是一个通用解法,这样就需要两个栈。同样我们可以改变栈中保存值,来实现单栈解法。

辅助栈解法

思路很简单,采用一个数据栈保存数据,一个辅助栈保存当前状态下的最小值。

步骤操作数据栈辅助栈最小值
1压入3333
2压入43, 43, 33
3压入23, 4, 23, 3, 22
4压入13, 4, 2, 13, 3, 2, 11
5弹出3, 4, 23, 3, 22
6弹出3, 43, 33
7压入03, 4, 03, 3, 00

最小值为辅助栈的栈顶

以下为具体解答:

private Stack<Integer> dataStack = new Stack<>();
private Stack<Integer> minStack = new Stack<>();

public void push(int node) {
    dataStack.push(node);
        
    if (minStack.isEmpty() || node < minStack.peek()) {
        minStack.push(node);
    } else {
        minStack.push(minStack.peek());
    }
}

public void pop() {
    dataStack.pop();
    minStack.pop();
}

public int top() {
    return dataStack.peek();
}

public int min() {
    return minStack.peek();
}

单栈解法

此时数据栈中保存的肯定不是实际的数据,我们引入一个类变量 min 用于保存当前时刻的最小值,数据栈中保存的是相对于 min 的变化值。
举例说明
当min 为 2 时。

  • 压入 3,数据栈压入3 - 2 = 1;
  • 压入 1,数据栈压入1 - 2 = -1,同时min更新为 1。
  • 弹出时,检查数据栈的栈顶元素,若大于 0,说明上次压入没有更新 min 的值,直接弹出栈顶;若小于 0 ,则需要更新 min 为 newMin = oldMin - 栈顶元素。

注意该方法数据栈压入的是long数据类型。这是由于变化值若为Integer.MAX_VALUE - Integer.MIN_VALUE 的话就超出Integer的范围了。

以下为具体解答:

private Stack<Long> stack = new Stack<>();;
private long min;

public void push(int node) {
    if (stack.empty()) {
        stack.push((long)0);
        min = node;
    } else {
        stack.push((long)node-min);
        if (node < min) {
            min = node;
        }
    }
}

public void pop() {
    if (!stack.empty()) {
        if (stack.peek() < 0) {
            min = min - stack.peek();
        }
        stack.pop();
    }
}

public int top() {
    if (stack.empty()) {
        throw new RuntimeException("empty stack");
    } else {
        if (stack.peek() > 0) {
            return (int)(min + stack.peek());
        } else {
            return (int)min;
        }
    }
}

public int min() {
    if (stack.empty()) {
        throw new RuntimeException("empty stack");
    } else {
        return (int)min;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值