一套模板搞定二叉树算法题--二叉树算法讲解002
1、二叉樹的遞歸
遞歸:
2、二叉樹遍歷之DFS深度優(yōu)先遍歷
2.1、遍歷的概念
每個節(jié)點 都要恰好被訪問一次,本質(zhì)上是二叉樹的線性化 。
一個樹形的結(jié)構(gòu),線性化為一個數(shù)組之類的"串"的結(jié)構(gòu)。
2.2、DFS深度優(yōu)先遍歷
示例二叉樹原型圖:
2.2.1、前序遍歷
前序遍歷執(zhí)行順序:
根節(jié)點--對左子樹做前序遍歷--對右子樹做前序遍歷
總的順序:根節(jié)點--左子樹--右子樹
左子樹中:根-左-右
根節(jié)點
右子樹中:根-左-右
對A的左子樹做前序遍歷
A的左子樹的根節(jié)點是B
對B的左子樹做前序遍歷
對B的右子樹做前序遍歷
對E的左子樹前序遍歷
至此,A的左子樹做完了前序遍歷:
然后,對A的右子樹做前序遍歷:
至此,二叉樹的前序遍歷完成。
我們會發(fā)現(xiàn),整個深度優(yōu)先的遍歷過程都是 遞歸的。
2.2.2、中序遍歷
中序遍歷執(zhí)行順序:
對左子樹做中序遍歷--根節(jié)點--對右子樹做中序遍歷
總的順序:左子樹--根節(jié)點--右子樹
左子樹中:左--根-右
根節(jié)點
右子樹中:左-根-右
2.2.3、后序遍歷
后序遍歷執(zhí)行順序:
對左子樹做后續(xù)遍歷--對右子樹做后續(xù)遍歷--根節(jié)點
總的順序:左子樹--右子樹--根節(jié)點
左子樹中:左--右-根
根節(jié)點
右子樹中:左-右-根
2.2.4、總結(jié)
所謂前序、中序、后序的區(qū)別。
就是根在前、根在中、還是根在后?
左、右的順序都是不變的,從左到右。
3、DFS深度優(yōu)先遍歷之代碼實現(xiàn)
4、二叉樹三種深度遍歷
4.1 leetcode 144 前序遍歷
4.2 leetcode 94 中序遍歷
4.3 leetcode 145 后序遍歷
5、從深度遍歷序列還原二叉樹--經(jīng)典題
5.1、leetcode105 從前序與中序遍歷序列構(gòu)造二叉樹
題目:
題意:
題解思路:
前序:
前序的根:
前序的根確定為3
再根據(jù)中序確定左右子樹
根據(jù)前序和中序的遍歷規(guī)則確定20為右子樹的根:
總結(jié)步驟:
1、根據(jù)提供的前序數(shù)組的第一個元素,確定二叉樹的根節(jié)點
2、找到根節(jié)點后,在中序數(shù)組中,根據(jù)根節(jié)點切割左右
左邊為二叉樹左子樹內(nèi)容,右邊為二叉樹右子樹內(nèi)容
3、再將中序數(shù)組切割的左右,返回給前序,在重復步驟1、2做遞歸操作
再來一個示例樹講解步驟,強調(diào)遞歸的體現(xiàn):
找到根節(jié)點3和左子樹、右子樹
遞歸右子樹:
右子樹的根節(jié)點20和左子樹、右子樹
核心思路:
其實是個子數(shù)組的過程,即把2個大數(shù)組(前序和中序數(shù)組)不斷拆成更小的數(shù)組的過程
1個大數(shù)組的拆分過程,可以使用2個指針來做拆分這件事
實現(xiàn)過程中重要的3個指針:
pre_start、in_start、in_end、同時也會用到代表根節(jié)點的idx
3個指針的含義:
圖解:
遞歸:
下一次遞歸左子樹時:
pre_start 是 pre_start+1
in_start還是in_start不變
in_end是idx-1
下一次遞歸右子樹時:
pre_start 是 pre_start + (idx - in_start)+ 1
in_start是idx+1
in_end還是in_end
這樣我們就可以實現(xiàn)遞歸了。
可以再看一個類似的示例圖:
題解:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
# 對于任何一顆子樹:
# 根節(jié)點一定在前序遍歷數(shù)組的第一個位置
# 可以找到根節(jié)點在中序遍歷數(shù)組中的位置,其左邊為左子樹,右邊為右子樹
# 然后對左子樹和右子樹進行遞歸操作
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int], ) -> Optional[TreeNode]:
# 構(gòu)建一個哈希表,key為節(jié)點的值,value為節(jié)點在中序遍歷數(shù)組中的索引
# 方便直接通過節(jié)點值取到下標
dic = {val: i for i, val in enumerate(inorder)}
n = len(inorder)
# 遞歸入口
return self.help(dic, preorder, inorder, 0, 0, n-1)
def help(self, dic, preorder, inorder, pre_start, in_start, in_end):
# 遞歸終止條件:若遍歷區(qū)間不存在,返回空節(jié)點
if in_start > in_en
return None
# 獲得當前區(qū)間的根節(jié)點的值node_val,為preorder[pre_start]
node_val = preorder[pre_start]
# 獲得該節(jié)點在中序遍歷數(shù)組中的位置
idx_node = dic[node_val]
# 構(gòu)建節(jié)點node
node = TreeNode(node_val)
# 進行遞歸
# pre_start
# ↓
# 3 | 9 5 | 20 15 7
# ↑ ↑ 左子樹和右子樹的pre_start
# in_start in_end
# ↓ ↓
# 9 5 | 3 | 15 20 7
# ↑
# idx_node
# 9 5 | 3 | 15 20 7
# ↑ ↑ 左子樹的in_start和in_end
# ↑ ↑ 右子樹的in_start和in_end
node.left = self.help(dic, preorder, inorder, pre_start + 1, in_start, idx_node - 1)
node.right = self.help(dic, preorder, inorder, pre_start + (idx_node - in_start) + 1, idx_node + 1, in_end)
# 將該節(jié)點回傳
return node
注:
代碼中的 {val: i for i, val in enumerate(inorder)} 表示我們將 inorder 列表中的每個元素作為字典的鍵,將其索引作為對應的值。
例如,如果 inorder 是 [4, 2, 7, 5, 1, 3, 6] ,那么生成的字典 dic 將是 {4: 0, 2: 1, 7: 2, 5: 3, 1: 4, 3: 5, 6: 6} 。
5.2、leetcode106 從中序與后序遍歷序列構(gòu)造二叉樹
題目:
題解:
5.3、2023C-二叉樹的廣度優(yōu)先遍歷
題目:
題意和思路:
先根據(jù)中序和后序遍歷構(gòu)造二叉樹,再進行二叉樹的層序遍歷
相當于leetcode106和leetcode102這2題的組合。
6、二叉搜索樹
6.1、二叉搜索樹的概念和性質(zhì)
6.2、二叉搜索樹的查找
查找n次,每次有2個分支中的1個;
即為: \(2^n = k\)
\(n = log_2^k\)
每次查找只進入2個分支中的1個,所以時間復雜度為O(log(n))
可以理解為一種特殊的二分查找,和二分查找的時間復雜度是一樣的。
或者說二叉搜索樹是二分查找在樹形結(jié)構(gòu)上的體現(xiàn)。
6.2.1、二叉搜索樹查找代碼模板
6.2.2、二叉搜索樹查找--leetcode 700
題目和題意:
題解:
注意思考,遞歸子問題為什么要return?
如果對上述的return的寫法不熟悉,可以改為如下使用成員變量的寫法:
初始化成員變量 self.ans = None
6.3、二叉搜索樹的增加
6.3.1、二叉搜索樹的增加 -- leetcode 701
題目和題意:
題解:
6.3.2、二叉搜索樹的增加 -- 2023C 計算三叉搜索樹的高度
題目和題意
題解:
這題其中關鍵部分的解法(樹的插入部分)和 leetcode 701幾乎一樣。
6.3.3、二叉搜索樹的增加 -- leetcode 98 驗證二叉搜索樹
題目:
解題思路:
用二叉搜索樹的性質(zhì)
①、先中序遍歷出樹
②、再判斷樹的值是否從小到大排列的。
其中步驟1就是leetcode94 中序遍歷二叉樹。
題解:
注:
步驟1中序遍歷二叉樹可以這樣實現(xiàn)
也可以這樣回傳列表的方式實現(xiàn) 實現(xiàn)的方式多種多樣
7、總結(jié)
注:
文中截圖源自大佬: 閉著眼睛學數(shù)理化 課程內(nèi)容
總結(jié)
以上是生活随笔為你收集整理的一套模板搞定二叉树算法题--二叉树算法讲解002的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ 学习宝藏网站分享
- 下一篇: java信息管理系统总结_java实现科