二叉樹常見問題整理

2021-07-24 19:46:09 字數 2846 閱讀 3933

做leetcode二叉樹的題目做了不少,覺得有必要總結一下。因為題型多歸多,但其實無非就是dfs和bfs,總結一些常見的解法,對於加深這兩周演算法的理解很有幫助。

在做dfs的時候,主要思路是可以從上到下也可以從下到上,也就是分析每乙個子樹的根節點,然後分析該子樹的內部子樹或者外部子樹的根節點,以此得出遞迴關係,也即是分治的思想。同時,對於每個節點的處理嘗試利用前序、後序、中序遍歷三種方法。

做bfs的時候,主要思路是從上到下,一層一層進行分析。

leetcode 105和106題

1、利用前序和中序遍歷構建二叉樹。

構建一棵二叉樹,如果是通過dfs的方式的話,那麼分析每乙個子樹的根節點,將乙個大子樹分解成乙個乙個小的子樹,分治下去,也就可以得出遞迴。

比如,有前序1,2,4,5,3,中序4,2,5,1,3。從前序中,我們可以得出乙個條件:當前子樹的根節點。

對於整個子樹1,2,4,5,3,可以確定,1是該子樹根節點,然後去中序中找1,1的左邊是4,2,5,右邊是3。因為中序的性質是在遍歷完左子樹後遍歷當前根節點,所以說4,2,5就是1為父節點的乙個新的子樹。去前序中得到乙個新的前序+中序陣列對:2,4,5; 4,2,5,同理,2是該子樹根節點,4是左子樹,5在右子樹, 以此類推分治遞迴下去。找到遞迴關係後,每一層根節點完成當前任務,然後將構建子樹的任務交給左右子樹遞迴過程即可。同時,我們思考的過程是從上到下,但程式遞迴執行的過程是從下到上,這點需要注意。可以寫出**:

treenode buildtree(int preorder, int inorder) 

}//將新的構建任務遞迴交下去。

node.left = buildtree(arrays.copyofrange(preorder, 1, leftcount+1),arrays.copyofrange(inorder,0,leftcount));

node.right = buildtree(arrays.copyofrange(preorder, leftcount + 1, preorder.length ), arrays.copyofrange(inorder, leftcount + 1, inorder.length ));

return node;

}

2、利用後序和中序構建二叉樹。

思路類似,還是先找根節點!可以看到,當前整個子樹根節點可以通過後續確定,然後利用中序確定左右子樹來分治遞迴。思路類似。

leetcode 108和109題

1、通過有序陣列來構建一棵平衡二叉搜尋樹。

首先,對於乙個有序陣列,比如1,2,3,4,5,6。這裡採用dfs解題。前面說過分析dfs時針對每乙個子樹的根節點,通過各個子樹的根節點來尋找遞迴關係。

對於bst最上面的子樹,根節點就是有序陣列最中間的元素,令s = 0,e = 5,那麼mid = s +(e-s)/2 = 2。也就是3是整個子樹根節點,1,2是左子樹內容,4,5,6是右子樹內容。對於1,2有s = 0,e = 1,同理mid = 0,也就是1是該子樹根節點,2是右子樹內容。 以此類推很容易寫出遞迴:

treenode dfs(int s,int e,int nums)
這裡,建議畫出遞迴棧,方便理解。在思考遞迴時,是從上到下思考,由整體到區域性,但是程式執行時從下到上的,也就是dfs執行方式。是通過前序遍歷的方式,在陣列中依次拿出2,1,3,4,5,從下到上構建出bst,構建順序是dfs的前序方式。

2、通過有序鍊錶來構建一棵平衡二叉搜尋樹。

鍊錶和陣列不同了,陣列可以隨機訪問,而鍊錶只能順序訪問。所以,我們的思路應該是,依次將1,2,3,4,5填到bst的正確位置。利用類似1中的dfs,可以得到下圖的遞迴棧,也就是說這5個符合條件的點就是bst中的點。我們從鍊錶中依次拿出1,2,3,4,5,填入到這個樹結構並構造bst。可以看到,對於1,應該填在0->1的位置,2填在1->1的位置,然後3填在0->4,4填在3->4,其實也就是以中序遍歷的順序填進去。這樣一來,**也就出來了:

treenode dfs(int s, int e)
可以看到,在構建樹或者bst的過程中,找準根節點位置以及填放順序,來相應處理即可。

leetcode 102,103,107都是此類問題,此類問題十分簡單,可以採用bfs和dfs求解。

將一棵二叉樹按層級遍歷。

如果使用bfs,遍歷完一層後可以得到下一次的全部節點數,在每一次遍歷後一次性遍歷整個一層即可。

**類似:

queuequeue = new linkedlist<>();

queue.add(root);

while(!queue.isempty())

}

如果使用dfs,我們無法保證乙個層級的全部節點是同一時刻遍歷的,但是可以分時遍歷,也就是在dfs中新增乙個關於level的引數,將同一level的點加入到結果中。

dfs(treenode root,int level)
可以看到,利用level將節點新增到結果鍊錶相應位置,不管是正序,倒敘還是zigzag,都是相應計算的事,所以還是比較推薦dfs,簡單整潔。

二叉樹整理(五)

二叉樹前序遍歷序列中,第乙個元素總是樹的根節點的值。中序遍歷序列中,左子樹的節點的值位於根節點的值的左邊,右子樹的節點的值位 於根節點的值的右邊。遞迴解法 1 如果前序遍歷為空或中序遍歷為空或節點個數小於等於0,返回null。2 建立根節點。前序遍歷的第乙個資料就是根節點的資料,在中序遍歷中找到根節...

二叉樹習題整理(二)

編寫遞迴演算法,求二叉樹中以元素值為x的結點為根的子樹的深度 先遞迴找出x的位置,用p指向,然後找到子樹的深度 求樹的深度的思路 1 如果樹為空,則深度為0 2 如果樹不是空,那麼深度是左子樹的深度 1或右子樹的深度 1 int t644 bitree t,telemtype x bitree lo...

二叉樹 二叉樹

題目描述 如上所示,由正整數1,2,3 組成了一顆特殊二叉樹。我們已知這個二叉樹的最後乙個結點是n。現在的問題是,結點m所在的子樹中一共包括多少個結點。比如,n 12,m 3那麼上圖中的結點13,14,15以及後面的結點都是不存在的,結點m所在子樹中包括的結點有3,6,7,12,因此結點m的所在子樹...