程式碼隨想錄演算法訓練營第十七天|leetcode654. 最大二叉樹、leetcode617.合併二叉樹、leetcode700.二叉搜尋樹中的搜尋、leetcode98.驗證二叉搜尋樹

小方呀0524發表於2024-11-06

1 leetcode654. 最大二叉樹

題目連結:654. 最大二叉樹 - 力扣(LeetCode)

文章連結:程式碼隨想錄

影片連結:又是構造二叉樹,又有很多坑!| LeetCode:654.最大二叉樹_嗶哩嗶哩_bilibili

思路:跟上一道題從中序後序中返回一個二叉樹,好了,同理的思路就做出來咯,哈哈哈哈哈哈

1.1 自己的程式碼

# 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 constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        if len(nums) == 0:
            return None
        root_val = max(nums)
        root = TreeNode(root_val)
        if len(nums) == 1:
            return root
        ind = 0
        for i in range(len(nums)):
            if nums[i] == root_val:
                ind = i
                break
        nums_left = nums[:ind]
        nums_right = nums[ind+1:]
        root.left = self.constructMaximumBinaryTree(nums_left)
        root.right = self.constructMaximumBinaryTree(nums_right)
        return root

1.2影片後的思路

差異就是這個構造的二叉樹,因為一定有值,所以沒必要對其為0進行判斷,如果有一個值的話,就可以進行返回

# 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 constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        if len(nums) == 1:
            return TreeNode(nums[0])
        root = TreeNode(0)
        maxval = 0
        maxind = 0
        for i in range(len(nums)):
            if nums[i]>maxval:
                maxval = nums[i]
                maxind = i
        root.val = maxval
        if maxind>0:
            root.left = self.constructMaximumBinaryTree(nums[:maxind])
        if maxind<len(nums)-1:
            root.right = self.constructMaximumBinaryTree(nums[maxind+1:])
        return root

1.3 本題小結

  1. 這道題的第一種思路就是使用前序中序構造一個唯一的二叉樹,這麼做可以寫出來程式碼,但是會非常的冗餘
  2. 然後就是第二種遞迴,首先判斷什麼時候終止,就是這個二叉樹只有一個數值的時候,可以直接進行返回,這裡發現由於遞迴的原因,如果直接將資料使用max函式的話會直接報錯

2 leetcode617.合併二叉樹

題目連結:617. 合併二叉樹 - 力扣(LeetCode)

文章連結:程式碼隨想錄

影片連結:一起操作兩個二叉樹?有點懵!| LeetCode:617.合併二叉樹_嗶哩嗶哩_bilibili

思路:開始的時候,我想的是這個直接進行合併就行,但是發現有的二叉樹我連分開都不能分開,還是直接看影片來寫吧

2.1 影片後的思路

思路

不進行新的二叉樹定義,覆蓋的方法,就是將另一個二叉樹的值加過去就好了,其實理論上真的沒新的,就是自己想不出來

2.1.1 覆蓋的方法
# 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 mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        if root1==None:
            return root2
        if root2 == None:
            return root1
        
        root1.val += root2.val
        root1.left = self.mergeTrees(root1.left,root2.left)
        root1.right = self.mergeTrees(root1.right,root2.right)
        return root1
2.1.2 定義一個新的二叉樹
# 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 mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        if root1==None:
            return root2
        if root2 == None:
            return root1
        root = TreeNode(0)
        root.val = root1.val +root2.val
        root.left = self.mergeTrees(root1.left,root2.left)
        root.right = self.mergeTrees(root1.right,root2.right)
        return root

2.2 本題小結

  1. 寫到這裡的時候,我突然發現,這種題真的寫的不難,主要是思路上會有想不到的地方,每次卡殼了,但是聽影片聽了一點就會了
  2. 二叉樹合併其實和兩數相加也是同樣的原理,要學會舉一反三呀

3 leetcode700.二叉搜尋樹中的搜尋

題目連結:700. 二叉搜尋樹中的搜尋 - 力扣(LeetCode)

文章連結:程式碼隨想錄

影片連結:不愧是搜尋樹,這次搜尋有方向了!| LeetCode:700.二叉搜尋樹中的搜尋_嗶哩嗶哩_bilibili

思路:看到題目想使用前序遍歷,如果找到了這個值,那就可以返回這個樹了;但是吧寫的時候,不會了,,

3.1 基礎知識

二叉搜尋樹

二叉搜尋樹是一個有序樹:

  • 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
  • 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
  • 它的左、右子樹也分別為二叉搜尋樹

3.2 影片後的思路

3.2.1 遞迴法
# 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 searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if root ==None or root.val == val:
            return root
        result = TreeNode(0)
        if root.val <val:
            result = self.searchBST(root.right,val)
        if root.val >val:
            result =self.searchBST(root.left,val)
        return result
3.2.2 迭代法
# 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 searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        while root:
            if root.val>val:
                root = root.left
            elif root.val<val:
                root = root.right
            else:
                return root

3.3 本題小結

  1. 這道題首先是二叉搜尋樹的概念,左子樹永遠比根節點小,右子樹永遠比根節點大,根據這個思路往下寫就行了
  2. 對於遞迴而言,如果知道這個,就容易,不過目前沒徹底弄明白為什麼要賦值result
  3. 遞迴法,就是聽了會了,寫的時候懵了,看題解的時候徹底會了,有點聰明但不多哈哈哈哈哈哈哈

4 leetcode98.驗證二叉搜尋樹

題目連結:98. 驗證二叉搜尋樹 - 力扣(LeetCode)

文章連結:程式碼隨想錄

影片連結:你對二叉搜尋樹瞭解的還不夠! | LeetCode:98.驗證二叉搜尋樹_嗶哩嗶哩_bilibili

思路:哈哈哈哈哈哈,開始想的是如果左子樹和右子樹的值滿足二叉搜尋樹的情況,就可以返回True;結果寫的時候,根本不會寫,,

4.1 自己的程式碼

寫了一句有超級大問題的程式碼

if root.val>root.left.val and root.val<root.right.val:
            return True
        result = TreeNode(0)

這裡問題出在,只判斷了他的左右節點,沒有判斷左子樹和右子樹,二叉樹的概念有一些混淆!!!!

4.2 影片後的思路

看完了,但是怎麼說呢,感覺還是有一點點難度,寫起來有一點不知如何下手的感覺,,

重點:判斷這個問題的時候,其實很好的一個想法就是使用中序遍歷,因為這樣可以保證出來的值是從小到大排序的一個過程

4.2.1暴力搜尋法

這裡之前寫錯了一句話,非要先判斷正確的,後來發現其實上去對的可能在中間會出現錯誤,就會有問題。

# 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 isValidBST(self, root: Optional[TreeNode]) -> bool:
        self.vec = []
        self.traversal(root)
        for i in range(len(self.vec)-1):
            if self.vec[i]>=self.vec[i+1]:
                return False
        return True
    def traversal(self,node):
        if node ==None:
            return True
        self.traversal(node.left)
        self.vec.append(node.val)
        self.traversal(node.right)
4.2.2 使用極小值的方法

定義一個極值,然後就是在中序的時候比較當前值和極值的關係,做一個返回的操作

# 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 __init__(self):
        self.maxval = float('-inf')
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        if root == None:
            return True
        left = self.isValidBST(root.left)
        if root.val>self.maxval:
            self.maxval = root.val
        else:
            return False
        right = self.isValidBST(root.right)
        return left and right
4.2.3 雙指標的方法

這種方法就是定義一個前指標,然後比較前一個值和當前值的關係,如果遇到了不符合的就返回

# 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 __init__(self):
        self.pre = None
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        if root == None:
            return True
        left = self.isValidBST(root.left)
        if self.pre !=None and self.pre.val>=root.val:
            return False
        self.pre = root
        right = self.isValidBST(root.right)
        return left and right

4.3 本題小結

  1. 本題的主要難點對我而言,就是上去思路就錯了,其次分析二叉樹的題目沒有嚴格按照遍歷順序去思考,導致這個題目花費了挺多時間的
  2. 思路上的總結,首先,這個是驗證,所以傳入的是這個二叉樹,終止條件找不正確的,然後第三部就是遞迴的內部邏輯,按照這個來就容易一些
  3. 記住使用的是中序遍歷方法

5 今日小結

  1. 前兩道題是對遞迴方法的一個總結吧,我覺得是,相比而言就是比較中規中矩的遞迴方法
  2. 後兩道題是對二叉搜尋樹概念的掌握和理解,在寫的過程越來越對這種概念理解的清晰了,題目思路也順暢了很多
  3. 希望接下來我可以真的自己分析題目,感覺現在的程式碼都是看了影片才會,離開影片可能就不會了,,,

相關文章