1. 程式人生 > 其它 >劍指offer程式碼解析——面試題21包含min函式的棧

劍指offer程式碼解析——面試題21包含min函式的棧

題目:實現一個棧,要求使用O(1)時間獲取棧中最小值,O(1)執行pop、push操作。

   分析:要獲取棧的最小值,我們首先想到的思路就是使用一個全域性變數記錄最小值,當元素進棧時和該全域性變數進行比較,若小於該全域性變數,則更新最小值。這種方法有個致命的缺陷:如果這個最小值出棧了,那麼當前棧的最小值該如何確定?

   解決辦法:我們可以再建立一個棧b,棧b的高度始終與棧a保持一致,棧頂元素儲存當前棧a的最小值。

   入棧:當元素入棧a後,該元素與棧b的棧頂元素進行比較,若小於棧b的棧頂元素,則將該元素入棧b,否則,將棧b原本的棧頂元素再次入棧b。

   出棧:當棧a的棧頂元素出棧時,只需將棧b的棧頂元素也出棧即可。這樣,棧b的棧頂元素始終是棧a的最小值。

   首先,我們需要定義以下幾個成員變數:

	private int[] stack_a;//棧a底層使用陣列儲存
	private int[] stack_b;//用於儲存最小值的棧
	private int top_a = -1;//棧a的實際深度
	private int top_b = -1;//棧b的實際深度
	private int max;//棧的最大深度

   接著定義建構函式,用於初始化棧:

	/**
	 * 建構函式
	 * @param max 棧允許的最大深度
	 */
	public Stack(int max){
		this.max = max;
		//初始化棧的底層陣列
		stack_a = new int[max];
		//初始化用於儲存最小值的陣列
		stack_b = new int[max];
	}

   然後定義入棧函式:

	/**
	 * 入棧
	 * @param t 入棧的元素
	 * @return 返回入棧操作的結果
	 */
	public boolean push(int t){
		//若棧已滿
		if(top_a==max-1){
			System.out.println("棧已滿!");
			return false;
		}
		
		//入棧
		{
			//元素首先入棧a
			stack_a[++top_a] = t;
			//當前入棧元素與棧b的棧頂元素比較,若小與棧b的棧頂元素,則入棧b,否則將棧b的棧頂元素再次入棧
			if(top_b==-1 || t<stack_b[top_b])//PS:top_b==-1表示:如果棧b為空,則直接將當前值當作最小值入棧
				stack_b[++top_b]=t;
			else{
				stack_b[top_b+1]=stack_b[top_b];
				top_b++;
			}
		}
		return true;
	}

   最後定義出棧函式:

	/**
	 * 出棧
	 * @return 返回棧頂元素
	 */
	public int pop(){
		//若棧為空
		if(top_a==-1){
			System.out.println("棧為空!");
			return -1;
		}
		
		//棧不為空時可以出棧
		{
			//棧b的棧頂元素出棧
			top_b--;
			//棧a的棧頂元素出棧
			return stack_a[top_a--];
		}
	}

   緊接著我們定義獲取最小值函式:

	/**
	 * 獲取棧中的最小值
	 * @return 返回棧中最小值
	 */
	public int min(){
		//若棧為空
		if(top_a==-1){
			System.out.println("棧為空!");
			return -1;
		}
		
		//返回最小值
		return stack_b[top_b];
	}

   最後我們進行測試:

	/**
	 * 測試
	 */
	public static void main(String[] args){
		//建立最大容量為10的棧
		Stack stack = new Stack(10);
		
		//棧為空時出棧
		System.out.println("棧為空時出棧:");
		stack.pop();
		
		//入棧
		System.out.println("n1,2,3,4,5依次入棧:");
		stack.push(5);
		stack.push(4);
		stack.push(3);
		stack.push(2);
		stack.push(1);
		
		//最小值
		System.out.println("n最小值:"+stack.min());
		
		//出棧
		System.out.println("n出棧:"+stack.pop());

		//最小值
		System.out.println("n最小值:"+stack.min());
		
	}

   輸出結果如下:

棧為空時出棧: 棧為空! 1,2,3,4,5依次入棧: 最小值:1 出棧:1 最小值:2