设计一个有getMin功能的栈 程序员代码面试指南

章一 栈与队列

书买来好久了,一直没时间看,今天翻开开了一下,感觉挺有意思的。作者的思路解答简单清晰,可以先思考,再看解答,实在没看懂再看代码的思路。总之,很好的学习资料。

题目:1颗星

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

要求

1. pop,push,getMin操作的时间复杂度都为O(1)
2. 设计的栈可以使用现成的栈结构

思路

  刚开始看到题目一愣,想的比较简单:直接用一个静态域存最小值不就行了么。后来看了一下解答,发现自己想的太简单了,如果用static field只能保证一直push()的情况下能始终保存最小值,但pop()掉最小值之后就无法在O(1)的时间下找到剩下的stack中的最小值了。后来看了解答感觉豁然开朗,尤其是还有两种解法,看着图解能很快的编出程序来了。
  下面讲述真正的思路:设置两个栈,一个按正常栈存储,一个栈保存最小元素。第二个栈有两种思路:一种是只当有更小或同样的值push()进来的进栈,另一种是每当第一个栈有值push()进来的时候把当前栈的最小值放入第二个栈栈顶。思路一省空间,思路二省时间。思路二编程处理更方便。
  下面说下编程过程中遇到的小问题:
1. 本来想实现泛型的,后来发现比较的时候 <= 不能用,继承Comparable接口无法实现泛型类型E的compareTo()方法,上网没查到方法,好像通配符做不到。所以就以Integer类型为例了。
2. 注意检查空栈情况:这里说明下,throw new RuntimeException()是无需声明throws语句的,如果只是throw new Exception()的话,函数需要声明throws语句。
3. 注意短路运算符左右表达式的顺序
  更多讲解,请买书查看。

思路一程序:

package StackandQueue;
import java.util.Stack;

public class StackwithGetMin1 {
    //create two stacks for storage
    private Stack<Integer> stackData;
    private Stack<Integer> stackMin;

    //Constructor: initialize the member object until it's created.
    public StackwithGetMin1() {
        stackData = new Stack<>();
        stackMin = new Stack<>();
    }

    //push operation: push in the stackData first, then decide whether to push in the stackMin
    public void push(int newValue) {
        if(stackData.isEmpty() || newValue <= stackMin.peek()) {
            stackMin.push(newValue);
        } 
        stackData.push(newValue);
    }

    //Judge if the stack is empty first; then decide pop both the stacks or not
    public int pop()  {
        if(stackData.isEmpty()) {
            throw new RuntimeException("The stack is empty!!!");
        } 
        int ret = stackData.peek();
        if(ret == stackMin.peek()) {
            stackMin.pop();
        } 
        stackData.pop();
        return ret;
    }


    // just return the top value in the stackMin
    public int getMin()  {
        if(stackMin.isEmpty()) {
            throw new RuntimeException("The stack is empty!!!");
        } 
        return stackMin.peek();
    }

    //The main function is used for test!
    public static void main(String[] args) {
        StackwithGetMin1 stack = new StackwithGetMin1();
        int[] stackArr = {3, 4, 5, 1, 2, 1};
        for(int index = 0; index < stackArr.length; ++index) {
            stack.push(stackArr[index]);
        }
        for(int index = 0; index < stackArr.length; ++index) {
            System.out.println(stack.getMin());
            stack.pop();
        }
    }
}

思路2程序

package StackandQueue;
import java.util.Stack;

public class StackwithGetMin2 {

    private Stack<Integer> stackData;
    private Stack<Integer> stackMin;

    public StackwithGetMin2 () {
        stackData = new Stack<>();
        stackMin = new Stack<>();
    }

    public void push(int value) {
        stackData.push(value);
        if(stackMin.isEmpty() || (value <= stackMin.peek()) ) {
            stackMin.push(value);
        } else {
            stackMin.push(stackMin.peek());
        }
    }

    public int pop() {
        if(stackMin.isEmpty()) {
            throw new RuntimeException("The stack is already empty!!!");
        }
        int ret = stackMin.peek();
        stackMin.pop();
        stackData.pop();
        return ret;
    }

    public int getMin() {
        if(stackMin.isEmpty()) {
            throw new RuntimeException("The stack is already empty!!!");
        }
        return stackMin.peek();
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        StackwithGetMin2 stack = new StackwithGetMin2();
        int[] stackArr = {3, 4, 5, 1, 2, 1};
        for(int index = 0; index < stackArr.length; ++index) {
            stack.push(stackArr[index]);
        }
        for(int index = 0; index < stackArr.length; ++index) {
            System.out.println(stack.getMin());
            stack.pop();
        }
    }
}

泛型情况,compareTo()无法定义,求指教:

package StackandQueue;
import java.util.Stack;

public class StackwithGetMin3<E> implements Comparable<E> {  //anything wrong here?

    private Stack<E> stackData;
    private Stack<E> stackMin;

    public StackwithGetMin3 () {
        stackData = new Stack<>();
        stackMin = new Stack<>();
    }

    public void push(E value) {
        stackData.push(value);
        if(stackMin.isEmpty() || (value.compareTo(stackMin.peek()) <= 0) ) { //Here's the problem!!
            stackMin.push(value);
        } else {
            stackMin.push(stackMin.peek());
        }
    }

    public E pop() {
        if(stackMin.isEmpty()) {
            throw new RuntimeException("The stack is already empty!!!");
        }
        E ret = stackMin.peek();
        stackMin.pop();
        stackData.pop();
        return ret;
    }

    public E getMin() {
        if(stackMin.isEmpty()) {
            throw new RuntimeException("The stack is already empty!!!");
        }
        return stackMin.peek();
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        StackwithGetMin3<Integer> stack = new StackwithGetMin3<>();
        int[] stackArr = {3, 4, 5, 1, 2, 1};
        for(int index = 0; index < stackArr.length; ++index) {
            stack.push(stackArr[index]);
        }
        for(int index = 0; index < stackArr.length; ++index) {
            System.out.println(stack.getMin());
            stack.pop();
        }
    }

    @Override
    public int compareTo(E o) {
        // TODO Auto-generated method stub
        return 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值