[演算法總結] 6 道題搞定 BAT 面試——堆疊和佇列

wwwxmu發表於2018-09-04

本文首發於我的個人部落格:尾尾部落

0. 基礎概念

:後進先出(LIFO)

[演算法總結] 6 道題搞定 BAT 面試——堆疊和佇列

佇列:先進先出(FIFO)

[演算法總結] 6 道題搞定 BAT 面試——堆疊和佇列

1. 棧的 java 實現

import java.util.Arrays;

public class Stack {
    private int size = 0;  //棧頂位置
    private int[] array;
    
    public Stack(){
        this(10);
    }
    public Stack(int init) {   
        if(init <= 0){
            init = 10;
        }
        array = new int[init];
    }
    
    /**
     * 入棧操作
     * @param item 入棧的元素
     */
    public void push(int item){
        if(size == array.length){
            array = Arrays.copyOf(array, size*2);   //擴容操作
        }
        array[size++] = item;
    }
    
    /**
     * 獲取棧頂元素,但棧頂元素不出棧
     * @return 棧頂元素
     */
    public int peek(){
        if(size == 0){  //空棧
            throw new IndexOutOfBoundsException("棧是空的");
        }
        return array[size-1];
    }
    
    /**
     * 出棧,同時獲取棧頂元素
     * @return
     */
    public int pop(){
        int item = peek();  //獲取棧頂元素
        size--;  //直接使元素個數減1,不用清除元素,下次入棧會覆蓋舊元素的值
        return item;
    }
    
    /**
     * 判斷棧是否已滿
     * @return
     */
    public boolean isFull(){
        return size == array.length;
    }
    
    /**
     * 判斷棧是否為空
     * @return
     */
    public boolean isEmpty(){
        return size == 0;
    }
    
    public int getSize(){
        return size;
    }    
}
複製程式碼

2. 佇列的 java 實現

public class ArrayQueue {
    private final Object[] queue;  //宣告一個陣列
    private int head;
    private int tail;
    
    /**
     * 初始化佇列
     * @param capacity 佇列長度
     */
    public ArrayQueue(int capacity){
        this.queue = new Object[capacity];
    }
    
    /**
     * 入隊
     * @param o 入隊元素
     * @return 入隊成功與否
     */
    public boolean put(Object o){
        if(head == (tail+1)%queue.length){
            //說明隊滿
            return false;
        }
        queue[tail] = o;
        tail = (tail+1)%queue.length;  //tail標記後移一位
        return true;
    }
    
    /**
     * 返回隊首元素,但不出隊
     * @return
     */
    public Object peak() {
        if(head==tail){
            //隊空
            return null;
        }
        return queue[head];        
    }
    
    /**
     * 出隊
     * @return 出隊元素
     */
    public Object pull(){
        if(head==tail){
            return null;
        }
        Object item = queue[head];
        queue[head] = null;
        return item;
    }
    
    /**
     * 判斷是否為空
     * @return
     */
    public boolean isEmpty(){
        return head == tail;
    }
    
    /**
     * 判斷是否為滿
     * @return
     */
    public boolean isFull(){
        return head == (tail+1)%queue.length;
    }
    
    /**
     * 獲取佇列中的元素個數
     * @return
     */
    public int getsize(){
        if(tail>=head){
            return tail-head;
        }else{
            return (tail+queue.length)-head;
        }
    }    
}
複製程式碼

3. 用兩個棧實現佇列

劍指offer:用兩個棧實現佇列 LeetCode:Implement Queue using Stacks

class MyQueue {
    Stack<Integer> input = new Stack<Integer>();
    Stack<Integer> output = new Stack<Integer>();
    /** Push element x to the back of queue. */
    public void push(int x) {
        input.push(x);
    }
    /** Removes the element from in front of queue and returns that element. */
    public int pop() {
        peek();
        return output.pop();
    }
    /** Get the front element. */
    public int peek() {
        if(output.isEmpty()){
            while(!input.isEmpty())
                output.push(input.pop());
        }
        return output.peek();
    }
    /** Returns whether the queue is empty. */
    public boolean empty() {
        return input.isEmpty() && output.isEmpty();
    }
}
複製程式碼

4. 用佇列實現棧

LeetCode:Implement Stack using Queues

class MyStack {

    Queue<Integer> q1 = new LinkedList<Integer>();
    Queue<Integer> q2 = new LinkedList<Integer>();
    
    /** Push element x onto stack. */
    public void push(int x) {
        if(q1.isEmpty()){
            q1.add(x);
            for(int i = 0; i < q2.size(); i++){
                q1.add(q2.poll());
            }
        }else{
            q2.add(x);
            for(int i = 0; i < q1.size(); i++){
                q2.add(q1.poll());
            }
        }
    }
    
    /** Removes the element on top of the stack and returns that element. */
    public int pop() {
        return q1.isEmpty() ? q2.poll() : q1.poll();
    }
    
    /** Get the top element. */
    public int top() {
        return q1.isEmpty() ? q2.peek() : q1.peek();
    }
    
    /** Returns whether the stack is empty. */
    public boolean empty() {
        return q1.isEmpty() && q2.isEmpty();
    }
}
複製程式碼

5. 包含min函式的棧

劍指offer:包含min函式的棧 定義棧的資料結構,請在該型別中實現一個能夠得到棧最小元素的min函式。

class MinStack {
    Stack<Integer> stack = new Stack<Integer>();
    Stack<Integer> temp = new Stack<Integer>();
    
    public void push(int x) {
        stack.push(x);
        if(temp.isEmpty() || temp.peek() >= x)
            temp.push(x);
    }
    
    public void pop() {
        int x = stack.pop();
        int min = temp.peek();
        if(x == min)
            temp.pop();
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int getMin() {
        return temp.peek();
    }
}
複製程式碼

6. 棧的壓入、彈出序列

劍指offer:棧的壓入、彈出序列 輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否為該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對應的一個彈出序列,但4,3,5,1,2就不可能是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)

import java.util.ArrayList;
import java.util.Stack;
public class Solution {
    public boolean IsPopOrder(int [] pushA, int [] popA) {
        if(pushA.length != popA.length || 
               pushA.length == 0 ||
               popA.length == 0)
            return false;
        Stack<Integer> stack = new Stack<>();
        int index = 0;
        for(int i = 0; i < pushA.length; i++){
            stack.push(pushA[i]);
            while(!stack.empty() && stack.peek() == popA[index]){
                stack.pop();
                index++;
            }
        }
        return stack.empty();
    }
}
複製程式碼

相關文章