✿-9例题 栈、辅助栈--最小栈-155
一、题目
二、Java实现代码
1.第一种解法--单个栈(国际站最高票):
package shuJuJieGou.ZhanAndHash; import java.util.Stack; /** * @Author : ASUS and xinrong * @Version : 2020/11/7 & 1.0 * 栈、辅助栈 * 最小栈—155 * 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 * * push(x) —— 将元素 x 推入栈中。 * pop() —— 删除栈顶的元素。 * top() —— 获取栈顶元素。 * getMin() —— 检索栈中的最小元素。 * 注意:pop、top 和 getMin 操作总是在 非空栈 上调用。 * * 思路: * 1)审题:随时取出当前栈内的最小值 * 2)存在的问题:在对栈进行不断地操作中,栈内元素不好控制 * 3)解决办法: * (1)一个栈 (国际站最高票): 用一个自定义的变量来存当前栈内的最小值 √ * (2)增加辅助栈 * * 复杂度分析: * 时间复杂度:O(1),“出栈”、“入栈”、“查看栈顶元素”的操作不论数据规模多大, * 都只是有限个步骤,因此时间复杂度是:O(1)。 * 空间复杂度:O(N),这里 N 是读出的数据的个数。 */ public class MinStack { int min = Integer.MAX_VALUE; private Stack<Integer> stack; public MinStack() { stack = new Stack<>(); } public void push(int x) { //有等于号是因为,如果后来新入栈的元素等于当前的min(之前入栈的元素), // 它一样会被列为新的min---入两次栈,这样在后面出栈(出两次栈)的情况下才不会错 if (x <= min) { //原来的min再一次入栈是为了在最小元素(栈顶元素)出栈之后,它继承最小元素min stack.push(min); min = x; } stack.push(x); } public void pop() { //如果当前出栈的是最小元素 if (stack.pop() == min) { //最小元素就更新为下一个出栈的元素 //多的这次出栈是因为 push的时候多了一步将原来min再次入栈的操作 min = stack.pop(); } } public int top() { return stack.peek(); } public int getMin() { return min; } public static void main(String[] args) { MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); int min1 = minStack.getMin(); System.out.println("当前最小值:"+min1); System.out.println("栈顶元素出栈"); minStack.pop(); int top = minStack.top(); System.out.println("当前栈顶元素:"+top); int min2 = minStack.getMin(); System.out.println("当前最小值:"+min2); } }
2.第二种解法--栈、辅助栈
1)两个栈同步
package shuJuJieGou.ZhanAndHash; import java.util.Stack; /** * @Author : ASUS and xinrong * @Version : 2020/11/7 & 1.0 * 栈、辅助栈 * 最小栈—155 * 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 * * push(x) —— 将元素 x 推入栈中。 * pop() —— 删除栈顶的元素。 * top() —— 获取栈顶元素。 * getMin() —— 检索栈中的最小元素。 * 注意:pop、top 和 getMin 操作总是在 非空栈 上调用。 * * 思路: * 1)审题:随时取出当前栈内的最小值 * 2)存在的问题:在对栈进行不断地操作中,栈内元素不好控制 * 3)解决办法: * (1)一个栈 * (2)增加辅助栈: * 两个栈一直同步 一起增加或删除一个元素可以保证两个栈的元素数量一直相同 √ * 两个栈不一直同步 * * 复杂度分析: * 时间复杂度:O(1),“出栈”、“入栈”、“查看栈顶元素”的操作不论数据规模多大, * 都只是有限个步骤,因此时间复杂度是:O(1)。 * 空间复杂度:O(N),这里 N 是读出的数据的个数。 */ public class MinStack_Helper_Together { /**数据栈*/ private Stack<Integer> data; /**辅助栈*/ private Stack<Integer> helper; public MinStack_Helper_Together() { data = new Stack<>(); helper = new Stack<>(); } /** * 增加元素 * @param x */ public void push(int x) { //数据栈增加元素 data.add(x); //辅助栈也增加元素 if (helper.isEmpty() || helper.peek() >= x) { helper.add(x); } else { helper.add(helper.peek()); } } /** * 出栈 */ public void pop() { if (!data.isEmpty()) { helper.pop(); data.pop(); } } /** * 读取栈顶元素 * @return */ public int top() { if (!data.isEmpty()) { return data.peek(); } throw new RuntimeException("栈中元素为空,此操作非法!"); } /** * 取出当前栈中最小的元素 * @return */ public int getMin() { if (!helper.isEmpty()) { return helper.peek(); } throw new RuntimeException("栈中元素为空,此操作非法!"); } public static void main(String[] args) { MinStack_Helper_Together minStack = new MinStack_Helper_Together(); minStack.push(-2); minStack.push(0); minStack.push(-3); int min1 = minStack.getMin(); System.out.println("当前最小值:"+min1); System.out.println("栈顶元素出栈"); minStack.pop(); int top = minStack.top(); System.out.println("当前栈顶元素:"+top); int min2 = minStack.getMin(); System.out.println("当前最小值:"+min2); } }
2)两个栈不同步
package shuJuJieGou.ZhanAndHash; import java.util.Stack; /** * @Author : ASUS and xinrong * @Version : 2020/11/7 & 1.0 * 栈、辅助栈 * 最小栈—155 * 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 * push(x) —— 将元素 x 推入栈中。 * pop() —— 删除栈顶的元素。 * top() —— 获取栈顶元素。 * getMin() —— 检索栈中的最小元素。 * 注意:pop、top 和 getMin 操作总是在 非空栈 上调用。 * * 思路: * 1)审题:随时取出当前栈内的最小值 * 2)存在的问题:在对栈进行不断地操作中,栈内元素不好控制 * 3)解决办法: * (1)一个栈 * (2)增加辅助栈: * 两个栈一直同步 * 两个栈不一直同步 出栈同步即可 √ * * 复杂度分析: * 时间复杂度:O(1),“出栈”、“入栈”、“查看栈顶元素”的操作不论数据规模多大, * 都只是有限个步骤,因此时间复杂度是:O(1)。 * 空间复杂度:O(N),这里 N 是读出的数据的个数。 */ public class MinStack_Helper { /**数据栈*/ private Stack<Integer> data; /**辅助栈*/ private Stack<Integer> helper; public MinStack_Helper() { data = new Stack<>(); helper = new Stack<>(); } /** * 入栈 * @param x */ public void push(int x) { data.add(x); //辅助栈在必要的情况下才添加 if (helper.isEmpty() || helper.peek() >= x) { helper.add(x); } } /** * 出栈 */ public void pop() { if (!data.isEmpty()) { // 注意:声明成 int 类型,这里完成了自动拆箱,从 Integer 转成了 int,因此下面的比较可以使用 "==" 运算符 // 如果把 top 变量声明成 Integer 类型,下面的比较就得使用 equals 方法 int pop = data.pop(); //辅助栈的栈顶元素等于刚刚出去的元素,那它也出栈 if (pop == helper.peek()) { helper.pop(); } } } /** *获取栈顶元素 * @return */ public int top() { if (!data.isEmpty()) { return data.peek(); } throw new RuntimeException("栈内元素为空,此操作非法!"); } /** * 获取当前栈的最小元素 * @return */ public int getMin() { if (!helper.isEmpty()) { return helper.peek(); } throw new RuntimeException("栈内元素为空,此操作非法!"); } public static void main(String[] args) { MinStack_Helper minStack = new MinStack_Helper(); minStack.push(-2); minStack.push(0); minStack.push(-3); int min1 = minStack.getMin(); System.out.println("当前最小值:"+min1); System.out.println("栈顶元素出栈"); minStack.pop(); int top = minStack.top(); System.out.println("当前栈顶元素:"+top); int min2 = minStack.getMin(); System.out.println("当前最小值:"+min2); } }