設計一個有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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章