程式碼隨想錄演算法訓練營第十三天

小方呀0524發表於2024-10-30

1 二叉樹的理論基礎

文章連結:程式碼隨想錄

影片連結:關於二叉樹,你該瞭解這些!| 二叉樹理論基礎一網打盡,二叉樹的種類、二叉樹的儲存方式、二叉樹節點定義、二叉樹的遍歷順序_嗶哩嗶哩_bilibili

1.1 二叉樹的種類

  1. 滿二叉樹

所有節點處的值都排滿了,沒有空的

  1. 完全二叉樹

只有在最後一層的時候,從左至右是順序儲存,且空的位置只能在右邊,左邊不能有空的

  1. 二叉搜尋樹

這種就是滿足左邊數值中滿足所有數值都小於根節點數,右邊的數值滿足所有數值都大於根節點數

  1. 平衡二叉搜尋樹

滿足二叉搜尋樹的基本要求後,其左右節點的高度差不超過1

1.2 二叉樹的儲存方式

鏈式儲存和順序儲存

  1. 鏈式儲存

這種方式就是相當於之前學的連結串列一樣,每一個值擁有左指標和右指標,最後一層的左右指標指向空位置即可

  1. 順序儲存

就相當於陣列的儲存,先儲存父節點,然後在儲存子節點,一步一步下來

1.3 二叉樹的遍歷方式

深度遍歷和廣度遍歷

  1. 深度遍歷

這種是先向下遍歷;這個分為三種:前序遍歷,中序遍歷和後續遍歷;前序遍歷是中左右,中序遍歷是左中右,後續遍歷是左右中;這個前後的順序其實是指中節點在哪個位置

  1. 廣度遍歷

這種方式就是橫著遍歷的,就可以使用了

1.4 二叉樹的定義方式

這個定義就是需要定義一個值,和左右節點,即指標即可

class TreeNode:
    def __init__(self,val,left=None,right=None):
        self.val = val
        self.left = left
        self.right = right

2 二叉樹的遞迴遍歷

文章連結:程式碼隨想錄

影片連結:每次寫遞迴都要靠直覺? 這次帶你學透二叉樹的遞迴遍歷!| LeetCode:144.前序遍歷,145.後序遍歷,94.中序遍歷_嗶哩嗶哩_bilibili

自己的思路:害,這種題真的就是,一看就會,一做就廢

2.1 遞迴演算法的三部曲

  1. 確定遞迴函式的引數和返回值
  2. 確定終止條件
  3. 確定單層遞迴的邏輯

2.2 遞迴的三道題

每次新增的值都是中序的值,其他的就向下遍歷

思考:為什麼不是左的值和右的值?

因為左和右的值她的下面還有下一層值,無限迴圈,,,

2.2.1 前序遍歷

題目連結:144. 二叉樹的前序遍歷 - 力扣(LeetCode)

前序的順序是中左右,所以先新增中序的值,遇到左右繼續遍歷

# 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
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        result = []
        def res(node):
            if node == None:
                return
            result.append(node.val)
            res(node.left)
            res(node.right)
        res(root)
        return result
2.2.2 中序遍歷

題目連結:94. 二叉樹的中序遍歷 - 力扣(LeetCode)

中序遍歷是左中右的順序,按照這個往下寫就行

# 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
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        result = []
        def dfs(node):
            if node == None:
                return
            dfs(node.left)
            result.append(node.val)
            dfs(node.right)
        dfs(root)
        return result
2.2.3 後序遍歷

題目連結:145. 二叉樹的後序遍歷 - 力扣(LeetCode)

後序遍歷過程中,其內部的結構為左右中

# 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
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        result = []
        def dfs(node):
            if node == None:
                return
            dfs(node.left)
            dfs(node.right)
            result.append(node.val)
        dfs(root)
        return result

2.3 本題小結

  1. 從這道題來理解的話,會發現遞迴不難,但是自己去寫邏輯還是有轉不過來的時候
  2. 主要就是函式呼叫的時候會很吃力,不知道為什麼

3 二叉樹的層序遍歷思路

文章連結:程式碼隨想錄

影片連結:講透二叉樹的層序遍歷 | 廣度優先搜尋 | LeetCode:102.二叉樹的層序遍歷_嗶哩嗶哩_bilibili

3.1 層序遍歷的解題思路

  1. 首先判斷整個結尾有沒有空,空的話就返回一個空列表
  2. 對其進行層序遍歷,首先是將其值全部儲存到佇列中,然後一個個彈出,增加現在的位置的值,最終進行值返回

3.2 leetcode102.二叉樹的層序遍歷

題目連結:102. 二叉樹的層序遍歷 - 力扣(LeetCode)

3.2.1 佇列的方法
import collections
# 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
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root == None:
            return []
        queue = collections.deque([root])
        result =[]
        while queue:
            level =[]
            for _ in range(len(queue)):
                cur = queue.popleft()
                level.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(level)
        return result
3.2.2 遞迴的方法
import collections
# 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
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root == None:
            return []
        result =[]
        
        def dfs(node,level):
            if node ==None:
                return
            if len(result)==level:
                result.append([])
            result[level].append(node.val)
            dfs(node.left,level+1)
            dfs(node.right,level+1)
        dfs(root,0)
        return result

3.3 leetcode 107二叉樹的層序遍歷 II

題目連結:107. 二叉樹的層序遍歷 II - 力扣(LeetCode)

3.2.1 佇列的方法

其實將上一道題進行一個倒序就好了

import collections
# 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
class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root == None:
            return []
        queue = collections.deque([root])
        result = []
        while queue:
            level = []
            for _ in range(len(queue)):
                cur = queue.popleft()
                level.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(level)
        return result[::-1]
3.2.2 遞迴的方法
import collections
# 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
class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root == None:
            return []
        
        result = []
        def dfs(node,level):
            if node == None:
                return
            if len(result) == level:
                result.append([])
            result[level].append(node.val)
            dfs(node.left,level+1)
            dfs(node.right,level+1)
        dfs(root,0)
        return result[::-1]

4 今日小結

  1. 怎麼說呢,感覺今天的題,學起來很容易,就是一學就會,但是一做就廢
  2. 內容上理解挺容易的,但是感覺因為佇列掌握不是很好,其實做就沒這麼容易了

相關文章