Day17 二叉樹Part5

haohaoscnblogs發表於2024-08-02

目錄
  • 任務
    • 654. 最大二叉樹
      • 思路
    • 617. 合併二叉樹
      • 思路
    • 700.二叉搜尋樹中的搜尋
      • 思路
    • 98. 驗證二叉搜尋樹
      • 思路(錯誤)
      • 思路(正確)
  • 心得體會

任務

654. 最大二叉樹

給定一個不重複的整數陣列 nums 。 最大二叉樹 可以用下面的演算法從 nums 遞迴地構建:
建立一個根節點,其值為 nums 中的最大值。
遞迴地在最大值 左邊 的 子陣列字首上 構建左子樹。
遞迴地在最大值 右邊 的 子陣列字尾上 構建右子樹。

思路

做了昨天的利用前中序(或者中後)陣列構建二叉樹,就會做這道題,思路基本一致。按照演算法,分割陣列區域並建立即可。

class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        if len(nums)==0: return None
        index = 0 
        maxValue = float('-inf')
        
        for i in range(len(nums)):
            if nums[i] > maxValue:
                maxValue = nums[i]
                index = i
        
        root = TreeNode(nums[index])
        leftNums = nums[:index]
        rightNums = nums[index+1:]
        root.left = self.constructMaximumBinaryTree(leftNums)
        root.right = self.constructMaximumBinaryTree(rightNums)
        return root

617. 合併二叉樹

想象一下,當你將其中一棵覆蓋到另一棵之上時,兩棵樹上的一些節點將會重疊(而另一些不會)。你需要將這兩棵樹合併成一棵新二叉樹。合併的規則是:如果兩個節點重疊,那麼將這兩個節點的值相加作為合併後節點的新值;否則,不為 null 的節點將直接作為新二叉樹的節點。
返回合併後的二叉樹。

思路

單層遞迴邏輯: 分情況合併當前節點

  1. 兩樹都不存在節點
  2. 兩樹只有一個存在,則返回有的那個
  3. 都存在,則將節點和相加並構建成新節點,並且分別遞迴的合併其左右子樹

這道題也是結合了遍歷過程和傳統遞迴的思路

class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root1 and not root2: return None
        if root1 and not root2: return root1
        if not root1 and root2: return root2
        if root1 and root2: 
            newRoot = TreeNode(root1.val + root2.val)
            newRoot.left = self.mergeTrees(root1.left,root2.left)
            newRoot.right = self.mergeTrees(root1.right,root2.right)
            return newRoot

700.二叉搜尋樹中的搜尋

思路

這道題很簡單,遞迴的思路就是遍歷節點,找到就返回,否則根據條件向相應的子樹去找。
迭代的思路是,val較小就往當前節點左子樹找,val較大就往當前節點的右子樹找,直到找到或者到達None.

# 遞迴法
class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root: return None
        if root.val == val: return root
        if val < root.val: return self.searchBST(root.left,val)
        else: return self.searchBST(root.right,val)

# 迭代法
class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        while root:
            if val < root.val: root = root.left
            elif val > root.val: root = root.right
            else: return root
        return None   

98. 驗證二叉搜尋樹

給你一個二叉樹的根節點 root ,判斷其是否是一個有效的二叉搜尋樹。

有效 二叉搜尋樹定義如下:

節點的左
子樹
只包含 小於 當前節點的數。
節點的右子樹只包含 大於 當前節點的數。
所有左子樹和右子樹自身必須也是二叉搜尋樹。

思路(錯誤)

想當然的解法是直接用遞迴,判斷當前節點的區域性邏輯是否滿足(它比它右節點小,比它左節點大),然後再判斷左右子樹是否滿足,全部滿足則返回True。可惜這種思路是錯誤的。。反例 [5,4,6,null,null,3,7], 某節點必須比他的左子樹所有的值小,右子樹所有的值大。這個7大於了根節點的大小,違反了BST的定義

class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        if not root: return True
        elif not root.left and not root.right: return True
        elif root.left and not root.right:
            if root.val > root.left.val: return True
            else:return False
        elif not root.left and root.right:
            if root.val < root.right.val: return True
            else:return False    
        else: 
            if root.val > root.left.val and  root.val < root.right.val:
                return self.isValidBST(root.left ) and self.isValidBST(root.right)
            else:
                return False

思路(正確)

判斷中序序列是否有序

class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        lst = []
        self.inorder(root,lst)
        print(lst)
        for i in range(len(lst)-1):
            if lst[i] >= lst[i+1]: return False
        return True

    def inorder(self,root,lst):
        if not root: return None
        
        self.inorder(root.left,lst)
        lst.append(root.val)
        self.inorder(root.right,lst)

心得體會

更嫻熟的掌握了單純遞迴邏輯(區域性+遞迴),以及遞迴序遍歷流程的思路。

相關文章