小白的深度優先搜尋(Depth First Search)學習日記(Python)

busakura發表於2024-04-09

1.二叉平衡樹

二叉平衡樹是指該樹的所有節點的左右子樹的深度相差不超過1.

題目:力扣110.平衡二叉樹

思路1:使用DFS對二叉樹進行後序遍歷,將每個節點的左右子樹的深度求出來,然後判斷該節點的左右子樹深度是否不超過1,將結果新增到全域性變數isBalance中。最後對isBalance進行遍歷,如果存在False,則該二叉樹不是平衡二叉樹,否則是平衡二叉樹。

程式碼:

點選檢視程式碼
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        isBalance = []
        def dfs(root:Optional[TreeNode]):
            if root is None:
                return 0
            left_nums = dfs(root.left)
            right_nums = dfs(root.right)
            if fabs(left_nums-right_nums)<=1:
                isBalance.append(True)
            else:
                isBalance.append(False)
            return max(left_nums,right_nums)+1
        dfs(root)
        if isBalance == []:
            return True
        for i in range(0,len(isBalance)):
            if isBalance[i]==False:
                return False
        return True
時間複雜度:由於要對二叉樹的每個節點都要遍歷一次,所以時間複雜度是O(n)

空間複雜度:由於實現宣告一個全域性變數存放每個節點是否滿足左右子樹深度相差不超過1,所以空間複雜度也為O(n)。
2.二叉樹的最小深度

題目:力扣111.二叉樹的最小深度

最小深度是指從根節點到最近葉子節點的最短路徑上的節點數量。

思路:求出每一個節點的最小深度,對於一個節點,如果它有左右子樹,則該節點的最小深度是左右子樹最小深度+1;如果該節點沒有左子樹或者沒有右子樹,則該節點的最小深度就是該節點的深度;如果該節點沒有孩子,則同樣,該節點的最小深度就是該節點的深度。綜上所述,對該二叉樹進行後序遍歷,判斷每一個節點的最小深度,最後返回二叉樹的最小深度。

程式碼:

點選檢視程式碼
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        def dfs(root:Optional[TreeNode]):
            if root is None:
                return 0
            left_depth = dfs(root.left)
            right_depth = dfs(root.right)
            if right_depth==0 or left_depth==0:
                return max(left_depth,right_depth)+1
            else:
                return min(left_depth,right_depth)+1
        return dfs(root)

時間複雜度:O(n)

空間複雜度:O(n)
3.路徑總和

題目:力扣112.路徑總和

思路:使用前序遍歷每一個節點,求出從根節點到每個葉子節點的路徑權值之和,然後從這些路徑和中尋找是否與目標一致的。

程式碼:

點選檢視程式碼
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if root is None:
            return False
        path_value = []
        def dfs(root:Optional[TreeNode],target_value):
            if root is None:
                return 
            target_value+=root.val
            ###判斷該點是否是葉子節點
            if root.left is None and root.right is None:
                path_value.append(target_value)
                return
            dfs(root.left,target_value)
            dfs(root.right,target_value)
        value=0
        dfs(root,value)
        for i in range(0,len(path_value)):
            if path_value[i]==targetSum:
                return True
        return False

時間複雜度:O(n)
空間複雜度:O(n)
4.二叉樹的前序遍歷

程式碼:

點選檢視程式碼
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]:
        nodes_val = []
        def dfs(root:Optional[TreeNode]):
            if root is None:
                return 
            nodes_val.append(root.val)
            dfs(root.left)
            dfs(root.right)
        dfs(root)
        return nodes_val

5.二叉樹的後序遍歷

程式碼:

點選檢視程式碼
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]:
        nodes_val = []
        def dfs(root:Optional[TreeNode]):
            if root is None:
                return 
            dfs(root.left)
            dfs(root.right)
            nodes_val.append(root.val)
        dfs(root)
        return nodes_val

6.翻轉二叉樹

思路:翻轉二叉樹,對於每一個節點都要對其左右子樹進行翻轉。這裡體現的一個思想就是自底向頂,從葉子節點開始,逐步往上,依次翻轉,所以採用後序遍歷,先遞到葉子節點,之後逐步歸,進行翻轉。

程式碼:

點選檢視程式碼
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root is None:
            return None
        def dfs(root:Optional[TreeNode]):
            if root is None:
                return 
            dfs(root.left)
            dfs(root.right)
            new_Node = root.left
            root.left = root.right
            root.right = new_Node
        dfs(root)
        return root
7.二叉樹的所有路徑

思路:前序遍歷二叉樹,對於遍歷到的每一個節點加入到當前路徑中,直到葉子節點,得到一條完整路徑,將其加入到列表中,直到得到所有路徑。

程式碼:

點選檢視程式碼
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        path = []
        def dfs(root:Optional[TreeNode],path_str):
            if root is None:
                return 
            path_str += str(root.val) + "->"
            ###如果該點是葉子節點,直接返回
            if root.left is None and root.right is None:
                path.append(path_str[:-2])
                return
            dfs(root.left,path_str)
            dfs(root.right,path_str)
        path_str=''
        dfs(root,path_str)
        return path

相關文章