如何获取栈的最小值

1、基本方法:增加辅助栈,辅助栈里面存储每次存放的最小值。如图所示原理,

代码实现:

public class MinStack1 {

	private List<Integer> data = new ArrayList<Integer>();
	private List<Integer> mins = new ArrayList<Integer>();

	public void push(int num) {
		data.add(num);
		if (mins.size() == 0) {
			// 初始化mins
			mins.add(num);
		} else {
			// 辅助栈mins每次push当时最小值
			int min = getMin();
			if (num >= min) {
				mins.add(min);
			} else {
				mins.add(num);
			}
		}
	}

	public int pop() {
		// 栈空,异常,返回-1
		if (data.size() == 0) {
			return -1;
		}
		// pop时两栈同步pop
		mins.remove(mins.size() - 1);
		return data.remove(data.size() - 1);
	}

	public int getMin() {
		// 栈空,异常,返回-1
		if (mins.size() == 0) {
			return -1;
		}
		// 返回mins栈顶元素
		return mins.get(mins.size() - 1);
	}
}

存在问题:

1.异常处理存在问题:这里定的是-1的异常返回值,但是当栈内为空的时候,返回的是-1,如果用户push过-1,那么返回的-1到底是用户push进来的值,还是栈为空,这个是个矛盾点。

2.辅助栈数据冗余的问题:

2、正确的解锁姿势(最优):用辅助栈记录存储数据最小值的下标。

mins 栈中改存最小值在 data 数组中的索引。这样一来,当 push 了与最小值相同元素的时候,就不需要动 mins 栈了。
而 pop 的时候,pop 出的元素的索引如果不是 mins 栈顶元素,mins 也不出栈。
同时,获取最小值的时候,需要拿到 mins 栈顶元素作为索引,再去 data 数组中找到相应的数作为最小值。
 

代码实现:

public class MinStack2 {

	private List<Integer> data = new ArrayList<Integer>();
	private List<Integer> mins = new ArrayList<Integer>();

	public void push(int num) throws Exception {
		data.add(num);
		if (mins.size() == 0) {
			// 初始化mins
			mins.add(0);
		} else {
			// 辅助栈mins push最小值的索引
			int min = getMin();
			if (num < min) {
				mins.add(data.size() - 1);
			}
		}
	}

	public int pop() throws Exception {
		// 栈空,抛出异常
		if (data.size() == 0) {
			throw new Exception("栈为空");
		}
		// pop时先获取索引
		int popIndex = data.size() - 1;
		// 获取mins栈顶元素,它是最小值索引
		int minIndex = mins.get(mins.size() - 1);
		// 如果pop出去的索引就是最小值索引,mins才出栈
		if (popIndex == minIndex) {
			mins.remove(mins.size() - 1);
		}
		return data.remove(data.size() - 1);
	}

	public int getMin() throws Exception {
		// 栈空,抛出异常
		if (data.size() == 0) {
			throw new Exception("栈为空");
		}
		// 获取mins栈顶元素,它是最小值索引
		int minIndex = mins.get(mins.size() - 1);
		return data.get(minIndex);
	}
}

 

 

参考资料:公众号互联网侦察

 

每天努力一点,每天都在进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

powerfuler

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值