设计一getMin的栈

题目:

实现一个特殊的栈,在实现栈的基本功能上,再实现返回栈中的最小元素

要求:

1. pop、push、getMin操作的时间复杂度都是O(1)

2. 设计的栈类型可以使用现成的栈

思路:

在设计的时候、我们使用两个栈、一个栈用来保存当前栈中的元素、其功能和一个正常的栈没有什么区别、这个栈记为stackData,另一个栈用来存当前的最小值、记为stackMin

第一种 设计方案

设计一getMin的栈_第1张图片
第一种设计流程图

(1)压入规则
① 如果stackMin为空直接压入newNum。
② 如果stackMin不为空,先是用getMin()查看stackMin栈顶元素,newNum和栈顶元比较,newNum小于等于,压入newNum、否则不压入。
③ 不管是那一不都必须把newNum压入stackData。
(2)弹出规则
弹出stackData的栈顶元素value、和stackMin的栈顶元素比较,如果等于弹出stackMin栈顶元素
(3)查询
就是使用栈的peek()方法查询stackMin的栈顶元素

代码演示


public class StackMin1 {

private StackstackData;

    private StackstackMin;

    public StackMin1() {

this.stackData =new Stack<>();

        this.stackMin =new Stack<>();

    }

/**

    * 进栈操作,如果栈中没有这直接加入两个栈,如果stackMin中有,newNum被stackMin的栈顶元素小则加入,

    * 否则不加入,

    *

    * @param newMun

    */

    public void push(int newMun) {

if (this.stackMin.isEmpty()) {

this.stackMin.push(newMun);

        }else if (newMun <=this.getMin()) {

this.stackMin.push(newMun);

        }

stackData.push(newMun);

    }

/**

    * 弹出方法

    *

    * @return

    */

    public int pop() {

if (this.stackData.isEmpty()) {

throw new RuntimeException("你还没有添加数据");

        }

int value =stackData.pop();

        if (value ==this.getMin()) {

this.stackMin.pop();

        }

return value;

    }

/**

    * 查看栈顶元素

    *

    * @return 返回栈顶元素

    */

    public int getMin() {

if (this.stackMin.isEmpty()) {

throw new RuntimeException("没有数据");

        }

//      查看存最小值的那个栈的栈顶元素

        return this.stackMin.peek();

    }

public static void main(String[] args) {

int[] arr = {3, 4, 5, 1, 2, 1};

        StackMin1 stackMin1 =new StackMin1();

        for (int i =0; i < arr.length; i++) {

stackMin1.push(arr[i]);

        }

for (int i =0; i < arr.length; i++) {

System.out.println(stackMin1.getMin()+" " +stackMin1.pop()  );

        }

}

}

第二种 设计方案

设计一getMin的栈_第2张图片
第二种方案流程图

(1)压入规则
① 如果stackMin为空直接压入newNum。
② 如果stackMin不为空,先是用getMin()查看stackMin栈顶元素,newNum和栈顶元比较,newNum小于等于,压入newNum、否则不压入。
③ 如果stackMin的栈顶元素较小,则在压入一遍
④ 不管是那一不都必须把newNum压入stackData。
(2)弹出规则
直接分别弹出stackMin和StackData即可
(3)查询
就是使用栈的peek()方法查询stackMin的栈顶元素

代码演示

class StackMin2 {

private StackstackMin;

    private StackstackData;

    public StackMin2() {

this.stackData =new Stack<>();

        this.stackMin =new Stack<>();

    }

public void push(int newNum) {

if (this.stackMin.isEmpty()) {

this.stackMin.push(newNum);

        }else if (newNum

this.stackMin.push(newNum);

        }else {

int min =this.getMin();

            this.stackMin.push(min);

        }

this.stackData.push(newNum);

    }

public int pop() {

if (this.stackMin.isEmpty()) {

throw new RuntimeException("没有数据了");

        }

this.stackMin.pop();

        return this.stackData.pop();

    }

public int getMin() {

if (this.stackMin.isEmpty()) {

throw new RuntimeException("没有数据");

        }

return this.stackMin.peek();

    }

}

总结:

两种方案的时间复杂度和空间复杂度都分别是O(1)、O(n),只是方法一:在压入的时候稍微省空间、但弹出的时候稍微费时间,方案二 在压入的时候稍微费空间、但弹出的时候稍微省时间。

文献:左程云著 《程序员代码面试指南IT名企算法与数据结构题目最优解》(第二版)
版权声明:此文版权归作者所有!

你可能感兴趣的:(设计一getMin的栈)