算法(16)-leetcode-explore-learn-数据结构-二叉树总结
leetcode-explore-learn-數(shù)據(jù)結(jié)構(gòu)-二叉樹3
- 1.根據(jù)中序和后序遍歷序列構(gòu)造二叉樹
- 2.根據(jù)前序和中序遍歷序列構(gòu)造二叉樹
- 3.填充每個(gè)節(jié)點(diǎn)的下一個(gè)右側(cè)節(jié)點(diǎn)指針
- 4.填充每個(gè)節(jié)點(diǎn)的下一個(gè)右側(cè)節(jié)點(diǎn)指針2
- 5.二叉樹的最近公共祖先
- 6.二叉樹的序列化和反序列化
本系列博文為leetcode-explore-learn子欄目學(xué)習(xí)筆記,如有不詳之處,請(qǐng)參考leetcode官網(wǎng):https://leetcode-cn.com/explore/learn/card/data-structure-binary-tree/2/traverse-a-tree/7/
所有例題的編程語(yǔ)言為python
二叉樹節(jié)點(diǎn)結(jié)構(gòu):
1.根據(jù)中序和后序遍歷序列構(gòu)造二叉樹
inorder=[9,3,15,20,7] 左根右
postorder=[9,15,7,20,3] 左右根,逆序就是根右左:[3,20,7,15,9]
由后序遍歷中可知根節(jié)點(diǎn)是3,在中序遍歷中可以確定左右子樹序列是多少。如何提取下一個(gè)根節(jié)點(diǎn)呢?取根和左右子樹遞歸構(gòu)造該如何銜接。
inorder 用來(lái)控制遞歸出口
postorder 才是提供根節(jié)點(diǎn)的源泉。
2.根據(jù)前序和中序遍歷序列構(gòu)造二叉樹
preorder=[3,9,20,15,7] 中左右
inorder=[9,3,15,20,7] 左中右
一個(gè)根節(jié)點(diǎn)可以將中序遍歷劃分為左一半,右一半。
全局變量pre_idx,每次運(yùn)行一次helper函數(shù)一次加1,取下一根節(jié)點(diǎn);直至左子樹運(yùn)行完,對(duì)應(yīng)的根節(jié)點(diǎn)下標(biāo)也應(yīng)該遍歷完全了。
剩余問(wèn)題:index不因該是根節(jié)點(diǎn)的在中序遍歷中的下標(biāo)么?左子樹包含的內(nèi)容不是應(yīng)該為[0,index-1] 根遞歸出口有關(guān),不是直接索引元素。
3.填充每個(gè)節(jié)點(diǎn)的下一個(gè)右側(cè)節(jié)點(diǎn)指針
填充一個(gè)完美二叉樹的每個(gè)解答的每個(gè)節(jié)點(diǎn)的下一個(gè)右側(cè)節(jié)點(diǎn)。完美二叉樹說(shuō)的是,所有葉子節(jié)點(diǎn)都在同一層。
思路:關(guān)鍵找到每一個(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn),那不就是二叉樹的層次遍歷。
每層的節(jié)點(diǎn)的next指針指其下一個(gè)節(jié)點(diǎn),用l來(lái)控制該層的最后一個(gè)節(jié)點(diǎn)指向None。
4.填充每個(gè)節(jié)點(diǎn)的下一個(gè)右側(cè)節(jié)點(diǎn)指針2
給定一個(gè)二叉樹,填充它每個(gè)next指針指向右側(cè)節(jié)點(diǎn),同一層的最右側(cè)節(jié)點(diǎn)填充為None.
思路:不是一棵完美的二叉樹,不過(guò)還是樹的層次遍歷,上一題的框架依舊可以使用。
代碼一點(diǎn)沒(méi)改能過(guò)。
5.二叉樹的最近公共祖先
給定一個(gè)二叉樹,找到該樹中兩個(gè)指定節(jié)點(diǎn)的最近公共祖先。
官方思路1:遞歸
遞歸遍歷整棵樹,定義fxf_xfx?表示x節(jié)點(diǎn)的子樹中是否包含p節(jié)點(diǎn)或者q節(jié)點(diǎn),如果包含則為true.采用自底向上從葉子節(jié)點(diǎn)開始更新,保證滿足條件的公共祖先深度最深。
官方思路2:儲(chǔ)存父節(jié)點(diǎn)
用hash表存儲(chǔ)所有節(jié)點(diǎn)的父親節(jié)點(diǎn),然后利用節(jié)點(diǎn)的父親節(jié)點(diǎn)的信息從p往上跳,直至根節(jié)點(diǎn),記錄已經(jīng)訪問(wèn)過(guò)的節(jié)點(diǎn);再?gòu)膓節(jié)點(diǎn)開始不斷往上跳,每次上跳一個(gè)節(jié)點(diǎn)就去p已訪問(wèn)的節(jié)點(diǎn)中尋找是否已經(jīng)訪問(wèn)過(guò)該節(jié)點(diǎn)。第一次遇到的p已經(jīng)訪問(wèn)的節(jié)點(diǎn),則該節(jié)點(diǎn)為答案。
難點(diǎn)1:父親節(jié)點(diǎn)hash表。{child1:root1,child2:root1},只要遍歷過(guò)二叉樹的所有節(jié)點(diǎn),就可以實(shí)現(xiàn)這個(gè)。
難點(diǎn)2:從p開始,不斷在父親hash表中找父親節(jié)點(diǎn),直至找不到父親節(jié)點(diǎn)的跟節(jié)點(diǎn),將所有路徑放入[]中。
技巧:還是將節(jié)點(diǎn)放進(jìn)去。
6.二叉樹的序列化和反序列化
將二叉樹序列化為一個(gè)字符串,將得到的字符串反序列化為二叉樹。
說(shuō)明:不要使用類成員/全局/靜態(tài)變量來(lái)存儲(chǔ)狀態(tài),序列化和反序列化算法應(yīng)該是無(wú)狀態(tài)的。–什么是無(wú)狀態(tài)?
序列化和反序列化遞歸順序一致就可以。
class Codec:def serialize(self, root):"""Encodes a tree to a single string.:type root: TreeNode:rtype: str"""def dfs_ser(node,string):if node==None:string+="None,"return stringstring+="{0},".format(node.val)string=dfs_ser(node.left,string)string=dfs_ser(node.right,string)return stringreturn dfs_ser(root,"")def deserialize(self, data):"""Decodes your encoded data to tree.:type data: str:rtype: TreeNode"""def rec_deser(lis):if lis[0]=="None":lis.pop(0)return Noneroot_val=lis[0]root=TreeNode(root_val) # 頂端lis.pop(0)root.left=rec_deser(lis) # 底端root.right=rec_deser(lis)return rootlis=data.split(",")return rec_deser(lis)總結(jié)
以上是生活随笔為你收集整理的算法(16)-leetcode-explore-learn-数据结构-二叉树总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: NLP复习资料(7)-机器翻译、文本分类
- 下一篇: tests1