[leetcode]Binary Search Tree Iterator,算法複雜度分析

題目在此:https://leetcode.com/problems/binary-search-tree-iterator/

描述:輸入爲一個二叉搜索樹,需要提供next和hasNext兩個函數接口。

約束條件:要求函數next、hasNext均能在O(1)的時間內返回,但允許的額外的存儲空間是O(h),其中h是二叉樹的高度。

解法:

一個直觀的想法是先遍歷二叉樹,存儲遍歷的結果,這樣就能在O(1)的時間完成next和hasNext函數。不過在準備階段需要O(n)的時間遍歷,同時需要O(n)的存儲空間。不滿足約束條件。

從約束條件“允許的額外的存儲空間是O(h)”出發,可以想到一個解法,就是保存好當前已遍歷的最小值,以及它所有的父節點,然後在執行next時做相應的操作即可。AC代碼如下:

public class BSTIterator {
	Stack<TreeNode> parents;
	TreeNode cur;

	private void pushLeft(TreeNode root){
		while (root != null) {
			parents.push(root);
			root = root.left;
		}
	}
	
	public BSTIterator(TreeNode root) {
		parents = new Stack<TreeNode>();
		pushLeft(root);	
	}

	/** @return whether we have a next smallest number */
	public boolean hasNext() {
		return !parents.isEmpty();
	}

	/** @return the next smallest number */
	public int next() {
		TreeNode cur = parents.pop();
		pushLeft(cur.right);
		return cur.val;
	}
}

代碼是已經AC了,但如上解法是否就滿足題目條件呢?答案是肯定的。

首先,棧parents在運行過程中其大小是O(h)的,這個結論很顯然;hasNext函數的執行時間,顯然也是O(1)的;但接下來問題來了,next函數是O(1)的麼?答案就不那麼明顯了。

我們可以看到,Next函數的時間複雜度隨着節點parents.peek()節點的不同而變化,要確定next 函數的時間複雜度確實不容易;但是,我們也要看到,總的來說,二叉搜索樹的每個節點都只會被訪問兩次(入棧和出棧),所以中的時間複雜度是O(n)的,而next函數總的訪問次數是n此,因此,我們可以說,next 函數的平均時間複雜度爲O(1)。這種時間複雜度的分析方法,就是平攤法。

關於平攤分析,更多可參考:http://blog.csdn.net/touzani/article/details/1696399


上述分析感想來自於:https://leetcode.com/discuss/20001/my-solutions-in-3-languages-with-stack



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章