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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

leetcode-explore-learn-數據結構-二叉樹3

  • 1.根據中序和后序遍歷序列構造二叉樹
  • 2.根據前序和中序遍歷序列構造二叉樹
  • 3.填充每個節點的下一個右側節點指針
  • 4.填充每個節點的下一個右側節點指針2
  • 5.二叉樹的最近公共祖先
  • 6.二叉樹的序列化和反序列化

本系列博文為leetcode-explore-learn子欄目學習筆記,如有不詳之處,請參考leetcode官網:https://leetcode-cn.com/explore/learn/card/data-structure-binary-tree/2/traverse-a-tree/7/

所有例題的編程語言為python
二叉樹節點結構:

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

1.根據中序和后序遍歷序列構造二叉樹

inorder=[9,3,15,20,7] 左根右
postorder=[9,15,7,20,3] 左右根,逆序就是根右左:[3,20,7,15,9]
由后序遍歷中可知根節點是3,在中序遍歷中可以確定左右子樹序列是多少。如何提取下一個根節點呢?取根和左右子樹遞歸構造該如何銜接。

inorder 用來控制遞歸出口
postorder 才是提供根節點的源泉。

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.根據前序和中序遍歷序列構造二叉樹

preorder=[3,9,20,15,7] 中左右
inorder=[9,3,15,20,7] 左中右
一個根節點可以將中序遍歷劃分為左一半,右一半。
全局變量pre_idx,每次運行一次helper函數一次加1,取下一根節點;直至左子樹運行完,對應的根節點下標也應該遍歷完全了。
剩余問題:index不因該是根節點的在中序遍歷中的下標么?左子樹包含的內容不是應該為[0,index-1] 根遞歸出口有關,不是直接索引元素。

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.填充每個節點的下一個右側節點指針

填充一個完美二叉樹的每個解答的每個節點的下一個右側節點。完美二叉樹說的是,所有葉子節點都在同一層。

思路:關鍵找到每一個節點的下一個節點,那不就是二叉樹的層次遍歷。
每層的節點的next指針指其下一個節點,用l來控制該層的最后一個節點指向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.填充每個節點的下一個右側節點指針2

給定一個二叉樹,填充它每個next指針指向右側節點,同一層的最右側節點填充為None.
思路:不是一棵完美的二叉樹,不過還是樹的層次遍歷,上一題的框架依舊可以使用。
代碼一點沒改能過。

5.二叉樹的最近公共祖先

給定一個二叉樹,找到該樹中兩個指定節點的最近公共祖先。
官方思路1:遞歸
遞歸遍歷整棵樹,定義fxf_xfx?表示x節點的子樹中是否包含p節點或者q節點,如果包含則為true.采用自底向上從葉子節點開始更新,保證滿足條件的公共祖先深度最深。

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) # 記錄左子樹的有沒有待識別的點right=rec(node.right,p,q) # 記錄右子樹有沒有待識別的點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:儲存父節點
用hash表存儲所有節點的父親節點,然后利用節點的父親節點的信息從p往上跳,直至根節點,記錄已經訪問過的節點;再從q節點開始不斷往上跳,每次上跳一個節點就去p已訪問的節點中尋找是否已經訪問過該節點。第一次遇到的p已經訪問的節點,則該節點為答案。
難點1:父親節點hash表。{child1:root1,child2:root1},只要遍歷過二叉樹的所有節點,就可以實現這個。
難點2:從p開始,不斷在父親hash表中找父親節點,直至找不到父親節點的跟節點,將所有路徑放入[]中。
技巧:還是將節點放進去。

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 # 要記得把自己放進去p=fa_hash[p]while(q!=None):if vis_hash.get(q): # 記得自己也要驗證return qq=fa_hash[q]

6.二叉樹的序列化和反序列化

將二叉樹序列化為一個字符串,將得到的字符串反序列化為二叉樹。
說明:不要使用類成員/全局/靜態變量來存儲狀態,序列化和反序列化算法應該是無狀態的。–什么是無狀態?

序列化和反序列化遞歸順序一致就可以。

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)

總結

以上是生活随笔為你收集整理的算法(16)-leetcode-explore-learn-数据结构-二叉树总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。