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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

一套模板搞定二叉树算法题--二叉树算法讲解002

發(fā)布時間:2024/1/16 windows 27 coder
生活随笔 收集整理的這篇文章主要介紹了 一套模板搞定二叉树算法题--二叉树算法讲解002 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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)容,希望文章能夠幫你解決所遇到的問題。

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