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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

二叉树层序遍历(广度优先搜索)基础概念与经典题目(Leetcode题解-Python语言)

發布時間:2023/12/4 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二叉树层序遍历(广度优先搜索)基础概念与经典题目(Leetcode题解-Python语言) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

二叉樹的廣度優先搜索即從上到下、從左到右地進行搜索,對于層序遍歷(Level Order)問題,即依次遍歷第一層節點、第二層節點…等,基本可以秒殺。

廣度優先搜索是通過隊列來實現的,python中優先用collections.deque,因為deque的 popleft() 比列表的 pop(0) 快不少。

劍指 Offer 32 - I. 從上到下打印二叉樹

import collections # leetcode里面可以去掉,下面都省略 class Solution:def levelOrder(self, root: TreeNode) -> List[int]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:node = queue.popleft()ans.append(node.val)if node.left: # 左子節點非空,加入隊列queue.append(node.left)if node.right: # 右子節點非空,加入隊列queue.append(node.right)return ans

從根節點開始,每個節點入隊之后,在出隊的時候把它的左右子節點也入隊(如果非空),則該隊列就完成了廣度優先搜索。

102. 二叉樹的層序遍歷 (劍指 Offer 32 - II. 從上到下打印二叉樹 II)

class Solution:def levelOrder(self, root: TreeNode) -> List[List[int]]:ans = list()if not root: # 判斷空樹return ansqueue = collections.deque()queue.append(root)while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)if node.left: # 左子節點非空,加入隊列queue.append(node.left)if node.right: # 右子節點非空,加入隊列queue.append(node.right)ans.append(curLevel)return ans

需要把同一層的節點放到同一個數組中,方法是用一個當前層數組 curLevel,通過循環每次把同一層的節點的子節點全部入隊,同時將這些節點的值記錄到curLevel 中,一層節點遍歷完之后將 curLevel 加入結果數組 ans 中。

103. 二叉樹的鋸齒形層序遍歷(劍指 Offer 32 - III. 從上到下打印二叉樹 III)

class Solution:def levelOrder(self, root: TreeNode) -> List[List[int]]:ans = list()if not root: # 判斷空樹return ansqueue = collections.deque()queue.append(root)odd = True # 奇偶層標志while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)if node.left: # 左子節點非空,加入隊列queue.append(node.left)if node.right: # 右子節點非空,加入隊列queue.append(node.right)if odd:ans.append(curLevel)odd = Falseelse:ans.append(curLevel[::-1])odd = Truereturn ans

按照之字形順序打印二叉樹,只需要加個奇偶層標志即可。

1609. 奇偶樹

class Solution:def isEvenOddTree(self, root: Optional[TreeNode]) -> bool:if not root: # 判斷空樹return anslevel = 0queue = collections.deque()queue.append(root)while queue:curLevel = []for i in range(len(queue)):node = queue.popleft()if (level % 2 == 0 and node.val % 2 == 0) or (level % 2 != 0 and node.val % 2 != 0):return Falseelse:if len(curLevel) == 0:curLevel.append(node.val)elif (level % 2 == 0 and node.val <= curLevel[-1]) or (level % 2 != 0 and node.val >= curLevel[-1]):return FalsecurLevel.append(node.val)if node.left: # 左子節點非空,加入隊列queue.append(node.left)if node.right: # 右子節點非空,加入隊列queue.append(node.right)level += 1return True

根據所在層數的奇偶,判斷節點值的奇偶以及遞增或遞減是否符合奇偶樹的要求。

107. 二叉樹的層序遍歷 II

class Solution:def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)ans.append(curLevel)return ans[::-1]

唯一區別就是輸出結果時倒轉輸出。

226. 翻轉二叉樹

class Solution:def invertTree(self, root: TreeNode) -> TreeNode:if not root:returnqueue = collections.deque()queue.append(root)while queue:for _ in range(len(queue)):node = queue.popleft()node.left, node.right = node.right, node.leftif node.left:queue.append(node.left)if node.right:queue.append(node.right)return root

層序遍歷時,交換節點的左右子節點,就完成了翻轉二叉樹,用前中后序遍歷的寫法見這篇文章。

104. 二叉樹的最大深度

class Solution:def maxDepth(self, root: Optional[TreeNode]) -> int:if not root:return 0queue = collections.deque()queue.append(root)depth = 0while queue:depth += 1for _ in range(len(queue)):node = queue.popleft()if node.left:queue.append(node.left)if node.right:queue.append(node.right)return depth

二叉樹的最大深度,就是二叉樹的層數。

111. 二叉樹的最小深度

class Solution:def minDepth(self, root: TreeNode) -> int:if not root:return 0queue = collections.deque()queue.append(root)depth = 1while queue:for i in range(len(queue)):node = queue.popleft()if not node.left and not node.right:return depthif node.left: # 左子節點非空,加入隊列queue.append(node.left)if node.right: # 右子節點非空,加入隊列queue.append(node.right)depth += 1

只需要用depth記錄層數,當遇到葉節點就返回depth,即為最小深度。

199. 二叉樹的右視圖

class Solution:def rightSideView(self, root: TreeNode) -> List[int]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:n = len(queue)for i in range(n):node = queue.popleft()if i == n - 1:ans.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)return ans

結果需要的是每一層的最右邊的數,因此循環到最右邊的數時,才將節點加入結果數組 ans。

513. 找樹左下角的值

class Solution:def findBottomLeftValue(self, root: TreeNode) -> int:if not root:return 0queue = collections.deque()queue.append(root)while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)return curLevel[0]

結果需要的是最底層的最左邊節點的值,因此用curLevel數組記錄每層的節點值,最后返回curLevel[0]就是最底層的最左邊節點的值。

1302. 層數最深葉子節點的和

class Solution:def deepestLeavesSum(self, root: Optional[TreeNode]) -> int:# 題目說了非空樹queue = collections.deque()queue.append(root)while queue:curLevel = 0for i in range(len(queue)):node = queue.popleft()curLevel += node.valif node.left:queue.append(node.left)if node.right:queue.append(node.right)return curLevel

返回最后一層的節點之和。

637. 二叉樹的層平均值

class Solution:def averageOfLevels(self, root: TreeNode) -> List[float]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:currLevel = list()n = len(queue)for i in range(n):node = queue.popleft()currLevel.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)ans.append(mean(currLevel))return ans

結果需要的是每一層的平均數,因此將平均數加入結果數組 ans。

515. 在每個樹行中找最大值

class Solution:def largestValues(self, root: TreeNode) -> List[int]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:currLevel = list()n = len(queue)for i in range(n):node = queue.popleft()currLevel.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)ans.append(max(currLevel))return ans

結果需要的是每一層的最大數,因此將最大數加入結果數組 ans。

1161. 最大層內元素和

class Solution:def maxLevelSum(self, root: TreeNode) -> int:if not root:return 0queue = collections.deque()queue.append(root)MaxValue = -float('inf')ans = 1depth = 1while queue:curLevel = 0for i in range(len(queue)):node = queue.popleft()curLevel += node.valif node.left:queue.append(node.left)if node.right:queue.append(node.right)if curLevel > MaxValue:MaxValue = curLevelans = depthdepth += 1return ans

目標是找到層值之和最大的那一層,記錄層數和最大值即可,注意 MaxValue 初始值要設成負無窮 -float(‘inf’) 。

429. N 叉樹的層序遍歷

""" # Definition for a Node. class Node:def __init__(self, val=None, children=None):self.val = valself.children = children """ import collections class Solution:def levelOrder(self, root: 'Node') -> List[List[int]]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)for child in node.children: # 區別if child:queue.append(child)ans.append(curLevel)return ans

N叉數是 children 列表而二叉樹是 left 和 right ,遍歷 children 即可。

116. 填充每個節點的下一個右側節點指針

class Solution:def connect(self, root: 'Node') -> 'Node':if not root:return rootqueue = collections.deque()queue.append(root)while queue:size = len(queue)for i in range(size):node = queue.popleft()if i < size - 1: # 必須使用 sizenode.next = queue[0]if node.left:queue.append(node.left)if node.right:queue.append(node.right)return root

層序遍歷一次二叉樹,記錄節點是隊列先進先出的,所以左邊的節點先出來,它的 next 就為 queue[0],注意 len(queue) 是會變化的,所以必須使用 size 記錄一層的長度

117 . 填充每個節點的下一個右側節點指針 II

class Solution:def connect(self, root: 'Node') -> 'Node':if not root:return rootqueue = collections.deque()queue.append(root)while queue:size = len(queue)for i in range(size):node = queue.popleft()if i < size - 1:node.next = queue[0]if node.left:queue.append(node.left)if node.right:queue.append(node.right)return root

不完美的二叉樹,但是和上一題一模一樣的代碼。

623. 在二叉樹中增加一行

class Solution:def addOneRow(self, root: TreeNode, val: int, depth: int) -> TreeNode:if depth == 1:new_root = TreeNode(val = val, left = root, right = None)return new_rootqueue = collections.deque()queue.append((root, 1))while queue:for _ in range(len(queue)):node, d = queue.popleft()if d == depth - 1:old_left = node.leftold_right = node.rightnode.left = TreeNode(val = val, left = old_left, right = None)node.right = TreeNode(val = val, left = None, right = old_right)else:if node.left:queue.append((node.left, d+1))if node.right:queue.append((node.right, d+1))return root

如果在第一行增加,那就是創建一個新的根節點,然后將原根節點作為左子節點。否則的話,就在隊列中使用多一個參數 d 來記錄深度,在 d - 1 層進行增加一行的操作,先記住節點原來的左右子節點 old_left 與 old_right,然后創建新的節點即可。關鍵是必須使用 for 循環,對整個第 d - 1 層都進行同樣的操作。

662. 二叉樹最大寬度

class Solution:def widthOfBinaryTree(self, root: Optional[TreeNode]) -> int:ans = 1if not root:return 0queue = collections.deque()queue.append((root, 1))while queue:cur = []for _ in range(len(queue)):node, pos = queue.popleft()cur.append(pos)if node.left:queue.append((node.left, 2 * pos - 1))if node.right:queue.append((node.right, 2 * pos))if max(cur) - min(cur) + 1 > ans:ans = max(cur) - min(cur) + 1return ans

在隊列中使用多一個參數 pos 來記錄位置,只需要記住的是,位置為 pos 的節點(從 1 開始)的左子節點位置是 2 * pos - 1,右子節點的位置是 2 * pos。

958. 二叉樹的完全性檢驗

class Solution:def isCompleteTree(self, root: TreeNode) -> bool:queue = collections.deque()queue.append((root, 1))depth = 0while queue:if len(queue) == 2**depth:for i in range(len(queue)):node, pos = queue.popleft()if node.left:queue.append((node.left, pos*2-1))if node.right:queue.append((node.right, pos*2))depth += 1else:for i in range(len(queue)):node, pos = queue.popleft()if node.left or node.right or (i+1) != pos:return Falsereturn True

與上一題類似的,關鍵是記錄節點的位置(注意位置從 1 開始)。在滿層中正常遍歷,一旦遇到不滿的層,如果其中有非葉子節點或者位置對不上則不是完全二叉樹。

993. 二叉樹的堂兄弟節點

class Solution:def isCousins(self, root: TreeNode, x: int, y: int) -> bool:# x 和 y 的深度與父節點x_depth, x_parent, y_depth, y_parent = None, None, None, None level = 0queue = collections.deque([(root, None)])while queue:n = len(queue)level += 1for i in range(n):node, node_parent = queue.popleft()# 每個節點的值都是唯一的if node.val == x:x_depth = levelx_parent = node_parentif node.val == y:y_depth = levely_parent = node_parentif node.left:queue.append((node.left, node))if node.right:queue.append((node.right, node))return x_depth == y_depth and x_parent != y_parent

由于題目中說明每個節點的值都是唯一的,所以用四個變量分別表示 x 和 y 的深度與父節點。然后在隊列中要同時記錄節點和節點的父節點,如果遇到值為 x 或 y 的節點就記錄其深度和父節點,最后進行比較即可。

總結

以上是生活随笔為你收集整理的二叉树层序遍历(广度优先搜索)基础概念与经典题目(Leetcode题解-Python语言)的全部內容,希望文章能夠幫你解決所遇到的問題。

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