思想
二叉樹的核心思想是分治和遞歸,特點是遍歷方式。
解題方式常見兩類思路:
- 遍歷一遍二叉樹尋找答案;
- 通過分治分解問題尋求答案;
遍歷分為前中后序,本質(zhì)上是遍歷二叉樹過程中處理每個節(jié)點的三個特殊時間點:
- 前序是在剛剛進入二叉樹節(jié)點時執(zhí)行;
- 后序是在將要離開二叉樹節(jié)點時執(zhí)行;
- 中序是左子樹遍歷完進入右子樹前執(zhí)行;
# 前序
1 node
/ \
2 left 3 right
中左右
# 中序
2 node
/ \
1 left 3 right
左中右
# 后序
3 node
/ \
1 left 2 right
左右中
多叉樹只有前后序列遍歷,因為只有二叉樹有唯一一次中間節(jié)點的遍歷
題目的關(guān)鍵就是找到遍歷過程中的位置,插入對應(yīng)代碼邏輯實現(xiàn)場景的目的。
實例
最大二叉樹 leetcode 654
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
輸入:
nums: List[int],一個不重復(fù)的整數(shù)數(shù)組
輸出:
TreeNode,根據(jù) nums 構(gòu)建一顆二叉樹,返回根節(jié)點。每個節(jié)點是當(dāng)前 nums 中的最大值,且左子樹是這個值左側(cè)的元素,右子樹是右側(cè)的元素。
舉例:
給定 [3,2,1,6,0,5]
最大值是 6,作為根節(jié)點,左子樹是 [3,2,1],右子樹是 [0,5]
左子樹中最大值是 3,作為左子樹的節(jié)點,他的左子樹是 [],右子樹是 [2,1]
右子樹中最大值是 5,作為右子樹的節(jié)點,他的左子樹是 [0],右子樹是 []
...
6
/ \
3 5
\ /
2 0
\
1
二叉樹的數(shù)據(jù)存儲可以使用鏈表,也可以使用數(shù)組,往往數(shù)組更容易表達,根節(jié)點從 index=1 處開始存儲,浪費 index=0 的位置
left_child = 2 * parent
right_child = 2 * parent + 1
parent = child // 2
分治解
基本情境是找到當(dāng)前構(gòu)建二叉樹的元素范圍,在這個范圍中找到值最大的元素和下標。
這個元素構(gòu)建一個二叉樹的根節(jié)點,下標左側(cè)是遞歸構(gòu)建二叉樹的新范圍,右側(cè)同理,左右子樹指針連接好后返回當(dāng)前根節(jié)點。
上例中
- 初始范圍是 0, 5,元素是 [3,2,1,6,0,5],其中的最大值是 6,下標是 3。構(gòu)建一個根節(jié)點 TreeNode(6),6.left = [3,2,1],6.right = [0, 5]
- 左子樹 [3,2,1] 的范圍是 0,2,,其中的最大值是 3,下標是 0。構(gòu)建一個根節(jié)點 TreeNode(3),3.left = [],3.right = [2,1]
- ...
編碼
from typing import Optional, List
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def maximum_binary_tree(nums: List[int]) -> Optional[TreeNode]:
def construct(left: int, right: int) -> Optional[TreeNode]:
# base 條件,返回樹的葉子的左右子樹的空指針節(jié)點
if left > right:
return None
# 找到范圍中的最大值和下標
max_int, max_index = None, None
for i in range(left, right + 1):
# 初始情況和當(dāng)前值比最大值大時,更新信息
if max_int is None or nums[i] > max_int:
max_int, max_index = nums[i], i
# 構(gòu)建二叉樹
root = TreeNode(max_int)
root.left = construct(left, max_index - 1)
root.right = construct(max_index + 1, right)
return root
# 邊界保護
if len(nums) == 0:
return None
return construct(0, len(nums) - 1)
相關(guān)
二叉樹 0
二叉樹 1
二叉樹 2
二叉樹 3
二叉樹 4
二叉樹 5
二叉樹 6
二叉樹 7
二叉樹 8
二叉樹 9
二叉樹 10
二叉樹 11
二叉樹 12