日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

算法(16)-leetcode-explore-learn-数据结构-二叉树总结

發(fā)布時(shí)間:2023/12/13 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法(16)-leetcode-explore-learn-数据结构-二叉树总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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):

class TreeNode(object):def __init__(self, x):self.val = xself.left = Noneself.right = None

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)的源泉。

class Solution(object):def buildTree(self, inorder, postorder):""":type inorder: List[int]:type postorder: List[int]:rtype: TreeNode"""global pos_indexpostorder.reverse()def helper(in_left=0,in_right=len(inorder)):global pos_indexif in_left==in_right:return Noneroot_val=postorder[pos_index]root=TreeNode(root_val)pos_index+=1in_index=inorder.index(root_val)root.right=helper(in_index+1,in_right)root.left=helper(in_left,in_index)return rootpos_index=0return helper()

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),不是直接索引元素。

class Solution(object):def buildTree(self, preorder, inorder):""":type preorder: List[int]:type inorder: List[int]:rtype: TreeNode"""global pre_indexdef helper(in_left=0,in_right=len(inorder)):global pre_indexif in_left==in_right:return Noneroot_val=preorder[pre_index]root=TreeNode(root_val)pre_index+=1in_index=inorder.index(root_val)root.left=helper(in_left,in_index)root.right=helper(in_index+1,in_right)return rootpre_index=0return helper()

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。

class Solution(object):def connect(self, root):""":type root: Node:rtype: Node"""if root==None:return None que=[root]while(que):l=len(que)for i in range(l):node=que.pop(0)if i==l-1:node.next=Noneelse:node.next=que[0]if node.left:que.append(node.left)if node.right:que.append(node.right)return root

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)開始更新,保證滿足條件的公共祖先深度最深。

class Solution(object):def __init__(self):self.ans=Nonedef lowestCommonAncestor(self, root, p, q):def rec(node,p,q):if node==None:return Falseleft=rec(node.left,p,q) # 記錄左子樹的有沒(méi)有待識(shí)別的點(diǎn)right=rec(node.right,p,q) # 記錄右子樹有沒(méi)有待識(shí)別的點(diǎn)mid=(node==p or node==q)if mid+left+right==2:self.ans=nodereturn mid or left or rightrec(root,p,q)return self.ans

官方思路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)去。

class Solution(object):def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""def dfs(node):if node==None:returnif node.left:fa_hash[node.left]=nodeif node.right:fa_hash[node.right]=nodedfs(node.left)dfs(node.right)fa_hash={root:None}vis_hash={}dfs(root) while (p!=None):# print(p)vis_hash[p]=True # 要記得把自己放進(jìn)去p=fa_hash[p]while(q!=None):if vis_hash.get(q): # 記得自己也要驗(yàn)證return qq=fa_hash[q]

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)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。