1. 程式人生 > 其它 >劍指offer程式碼解析——面試題22棧的壓入、彈出序列

劍指offer程式碼解析——面試題22棧的壓入、彈出序列

本題的詳細分析過程均在程式碼的註釋中:

import java.util.Stack;

/**
 * 題目:輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否為棧的彈出順序。
 * PS:設所有數字均不想等。
 * @author 大閒人柴毛毛
 * @date 2016年3月15日
 */
public class StackSequence {
	/**
	 * 棧的特點是不管入棧還是出棧,都只能對棧頂元素進行操作。
	 * 一個序列如果依次入棧,再依次出棧的話,序列將會被逆序輸出。
	 * 但如果在入棧的過程中隨機停止入棧操作,緊接著隨機出棧n個元素,這樣出棧順序將會千變萬化。
	 * 本題就是要求判斷某一個數組是否屬於指定入棧序列的出棧序列。
	 */
	
	/**
	 * 通過上述分析,最直觀的方法就是窮舉法,將一個入棧序列的所有出棧序列均羅列出來,然後判斷這些序列中是否含有指定的出棧序列。
	 * 由於窮舉法需要大量的時間、空間開銷,因此要儘量避免。下面介紹更加高效的演算法。
	 */
	
	/**
	 * 假設入棧序列為a,出棧序列為b。我們需要用一個全域性變數count來記錄當前匹配出棧序列的最大長度。
	 * 我們需要兩個指標i和j分別指向序列a和b。
	 * 準備工作完畢,下面開始演算法:
	 * 首先將a[i]入棧,
	 * 然後判斷棧頂元素與b[j]是否相等,若二者相等,則該元素出棧,並count++表示已匹配到一位出棧元素,並使j++,然後重複上述操作,直到i掃描完序列a。
	 * 最後判斷下匹配到的出棧元素個數是否與序列a的長度相同。
	 */
	
	/**
	 * 判斷出棧序列是否符合指定入棧序列的某一種出棧順序
	 * @param a 入棧序列
	 * @param b 出棧序列
 	 * @return 返回執行結果
	 */
	public static boolean isStackSequence(int[] a,int[] b){
		//若序列為空
		if(a==null || b==null || a.length<=0 || b.length<=0){
			System.out.println("序列為空!");
			return false;
		}
		
		//若入棧序列和出棧序列長度不等
		if(a.length != b.length){
			System.out.println("入棧序列與出棧序列長度不等!");
			return false;
		}
		
		//開始判斷
		{
			//建立棧
			Stack<Integer> stack = new Stack<Integer>();
			int i=0,j=0;
			while(i<a.length){
				//若棧為空,則a[i]入棧
				stack.add(a[i++]);
				//判斷棧頂元素和b[j]是否相等
				if(stack.peek()==b[j]){
					//棧頂元素出棧
					stack.pop();
					//j向後一位
					j++;
				}
			}
			
			//若棧中還有元素,則依次出棧,判斷出棧序列與b剩餘的序列是否相同
			while(!stack.isEmpty()){
				if(stack.pop()!=b[j])
					return false;
				else
					j++;
			}
			
			//判斷棧是否為空,若為空表示成功匹配,若不為空表示失敗
			if(!stack.isEmpty())
				return false; 
		}
		
		return true;
	}
	
	
	/**
	 * 測試
	 */
	public static void main(String[] args){
		//入棧序列
		int[] a = {1,2,3,4,5};
		//出棧序列
		int[] b = {4,3,5,1,2};
		System.out.println(isStackSequence(a,b));
	}
}