实现单栈实现支持getMin的栈

双栈实现getMin功能的问题

  左程云的《程序员代码面试指南》,第一个题是“设计一个有getMin功能”的栈,思路如下:

用到了双栈:

一个栈(stackData)用来保存当前栈中的元素,其功能和正常的栈没有区别;

另外一个栈(stackMin)用来保存每一步的最小值;

  2种方案思路就是下面这幅图所示:

  

  

  如果使用上面图中的数据,其实发现不了什么问题,但是可以进行如下操作:

getMin(); // 返回1
 // 直接从stackMin中获取栈顶元素,就是栈的最小值(1),正确

pop();
// stackData弹出1,同时stackMin中的栈顶元素所有1,然后stackMin栈顶元素为3,无异常

top(); // 返回2
// 从stackData获取栈顶元素(不出栈)

getMin(); // 返回3
// 从stackMin返回栈顶元素,但是返回的是3,而不是2,因为stackData的最小元素是2

  所以,书中的方案,并不能实现正确getMin功能,另外,如果换一组数据:0、1、0,画出的图如下:

    

  对于是上面的两个图,进行如下操作:

getMin(); // 返回0  正确

top();  // 返回0 正确

pop(); // stackData的栈顶元素0出栈,同时,stackMin的所有元素都会出栈
// 因为stackMin栈顶元素始终和stackData出站的元素相同,都为0

top();  // 返回1 正确

getMin(); // 出现异常,因为stackMin已经是个空栈了
// 预期是返回0,因为stackData的栈底元素是0,比top元素小

  其实对于上面这个问题,也可以这样修改:

  1.stackData仍旧保持不变;

  2.stackMin中不是只存一个int,而是存一个Item;

  3.Item有两个域,一个data域,表示本次push的值,另一个是min,表示push当前这个值后,stackData的最小值。

  原理如如下所示:

  

  其实,看了上面这个双栈,你会发现,stackData是多余的,因为stackMin中已经包含了所有需要的数据,stackData完全没有存在的必要,所以建议使用单栈来实现,不要使用双栈了,不仅麻烦,而且还多费一些空间;

单栈实现getMin功能

  使用单栈也比较简单,原理如下所示:

  

  Java实现代码如下:

package cn.ganlixin.ds;


import java.util.Stack;

class Item {
    // 每次push的值
    int data;

    // data入栈后,栈的最小值
    int min;

    public Item(int data, int min) {
        this.data = data;
        this.min = min;
    }
}

public class MinStack {

    //存放元素的栈
    private Stack<Item> stack = null;

    public MinStack() {
        stack = new Stack<>();

    }

    public void push(int x) {
        // 栈为空,则push进来的x就是最小值
        if (stack.isEmpty()) {
            stack.push(new Item(x, x));
        } else {

            // 获取栈顶元素,因为栈顶元素的min保存了push x之前的最小值
            Item top = stack.peek();

            // 如果栈顶元素的最小值比当前x要小,则新Item的min为top.min
            stack.push(new Item(x, top.min > x ? x : top.min));
        }
    }

    public void pop() {
        stack.pop();
    }

    public int top() {
        return stack.peek().data;
    }

    public int getMin() {
        return stack.peek().min;
    }
}

  

  测试:

public class TestMinStack {

    @Test
    public void test() {
        MinStack minStack = new MinStack();
        minStack.push(0);
        minStack.push(1);
        minStack.push(0);

        System.out.println(minStack.getMin());  // 0

        minStack.pop();
        System.out.println(minStack.top());     // 1

        System.out.println(minStack.getMin());  // 0
    }
}

  

原文地址:https://www.cnblogs.com/-beyond/p/13227736.html