6.4 數據結構---樹的深度


一、最大深度

1.二叉樹的最大深度 leetcode104

給定一個二叉樹,找出其最大深度。
二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。
說明: 葉子節點是指沒有子節點的節點。
示例:
給定二叉樹 [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
返回它的最大深度 3

  

思路1:深度優先搜索(遞歸)

終止條件:如果二叉樹為空,則深度為0;

遞歸體:如果不為空,分別求左子樹的深度和右子樹的深度,取最大的再加1

def maxDepth(root):
    """
    :type root: TreeNode
    :rtype: int
    """
    if root == None:
        return 0
    leftDepth = maxDepth(root.left) + 1
    rightDepth = maxDepth(root.right) + 1
    return leftDepth if leftDepth > rightDepth else rightDepth

  

思路2:把樹看做是圖,用dfs求最長長度的路徑

from collections import defaultdict
def maxDepth2(nodes):
    #輸入:nodes [3,9,20,null,null,15,7]

    #由節點列表構造圖的鄰接表
    def define_graph(arr):
        neig_dict = defaultdict(list)
        for i in range(len(arr)):
            if arr[i] != None:
                if (2*i+1) <= len(arr)-1 and arr[2*i+1]:#如果左節點存在
                    neig_dict[arr[i]].append(arr[2*i+1])
                if (2*i+2) <= len(arr)-1 and arr[2*i+2]:#如果右節點存在
                    neig_dict[arr[i]].append(arr[2*i+2])
                if (i-1)//2 >= 0 and arr[(i-1)//2]:#左子樹的父節點
                    neig_dict[arr[i]].append(arr[(i-1)//2])
                elif (i-2)//2 >= 0 and arr[(i-2)//2]:#右子樹的父節點
                    neig_dict[arr[i]].append(arr[(i-2)//2])
        return neig_dict

    #遍歷鄰接表,返回一次遍歷的長度
    def dfs(nei_dict,i,visit):
        for j in nei_dict[i]:
            if j not in visit:
                visit.add(j)
                dfs(neig_dict,j,visit)
        return len(visit)

    neig_dict = define_graph(nodes)
    init_node = nodes[0]#圖的起始點
    visit = set()
    visit.add(init_node)
    max_len = 0
    for i in neig_dict[init_node]:#遍歷初始點的所有鄰接點
        visit.add(i)
        max_len = max(dfs(neig_dict,i,visit),max_len)
        print('visit',visit)
        visit = set()#每遍歷完一條路徑之后,都要重新定義visit
        visit.add(init_node)
    return max_len

# res = maxDepth2([3,9,20,None,None,15,7])
# print("最大深度",res)

  

思路3:層次遍歷,計算有多少層,即為樹的深度

def maxDepth_leverOrder(arr,arr_level):
    def levelOrder(arr,i,arr_lever):#i是當前節點是index
        #先序遍歷樹的每一個節點,當前節點的層數等於上一層加一
        if (i-1)//2 >= 0 and arr[(i-1)//2]:#左節點存在
            arr_lever[i] = arr_lever[(i-1)//2] + 1#等於父節點層數加一
        elif (i-1)//2 >= 0 and arr[(i-1)//2]:#右節點存在
            arr_lever[i] = arr_lever[(i-1)//2] + 1

    for i in range(1,len(arr)):#遍歷除了根節點的其他節點
        if arr[i] == None:
            continue
        else:
            levelOrder(arr,i,arr_level)

    arr = [3,9,20,None,None,15,7]
    if len (arr) == 1:
        print(1)
    else:
        arr_level = defaultdict(int)
        arr_level[0] = 1  # 根節點為第一層

        print ('arr_level before',arr_level)
        maxDepth_leverOrder(arr,arr_level)
        print('arr_level after',arr_level)
        print('深度',max(arr_level.items(),key=lambda x:x[1]))#5,3==> 樹在列表中的index值,對應的深度

def level_Order_init(root):
    # 層次遍歷的遞歸寫法
    def maxDepth_leverOrder_recur(level, result, node):
        if node:
            print('level=%s,result長度=%s'%(level,len(result)))
            #level<len(result),說明有下一層,但是還沒放數據
            #level=len(result),說明有下一層且該層數據已經遍歷完
            if level == len(result):
                #說明該層數據已經遍歷完成,下一步要遍歷下一層的數據
                result.append([])
            result[level].append(node.val)#該層
            maxDepth_leverOrder_recur(level+1,result,node.left)#左,下一層
            maxDepth_leverOrder_recur(level+1,result,node.right)#右,下一層

    level,result = 0,[]
    maxDepth_leverOrder_recur(level,result,root)
    print('深度',len(result))
    return result

L1 = TreeNode(3)
L2 = TreeNode(9)
L3 = TreeNode(20)
L4 = TreeNode(15)
L5 = TreeNode(7)

L1.left = L2
L1.right = L3
L2.left = None
L2.right = None
L3.left = L4
L3.right = L5
res = level_Order_init(L1)
print(res)

  

2.N叉樹的最大深度 leetcode559

題目:給定一個N叉樹,找到其最大深度。最大深度是指從根節點到最遠葉子節點的最長路徑上的節點總數

思路:二叉樹求最大深度一樣,只是由固定的左右子節點變成了一堆子節點,方法沒變

  • 遞歸,如果node為空,直接返回
  • 遍歷node的所有孩子節點,取最大值+1作為最大深度
class TreeNode:
    def __init__(self, val, children):
        self.val = val
        self.children = children

def maxDepth(node):
    if node == None:
        return 0
    if not node.children:
        return 1

    #計算所有孩子節點的深度最大值
    # print('node.children',node.children)
    if len(node.children) >= 1:
        this_child_maxdpth = []
        for child in node.children:
            this_child_maxdpth.append(maxDepth(child)+1)
        return max(this_child_maxdpth)

L5 = TreeNode(5,None)
L6 = TreeNode(6,None)
L3 = TreeNode(2,None)
L4 = TreeNode(5,None)
L2 = TreeNode(3,children=(L5,L6))
L1 = TreeNode(1,children=(L2,L3,L4))
res = maxDepth(L1)
print(res)

  

 

二、最小深度

1.二叉樹的最小深度 leetcode111

題目:給定一個二叉樹,找出其最小深度。二叉樹的最小深度為根節點到最近葉子節點的距離。

思路1:計算左子樹和右子樹深度的時候,判斷是否等於0,如果等於0,說明該子樹不存在,深度賦值為最大值。

思路2:判斷左子樹或右子樹是否為空,若左子樹為空,則返回右子樹的深度,反之返回左子樹的深度,如果都不為空,則返回左子樹和右子

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

def minDepth(root):
    """
    :type root: TreeNode
    :rtype: int
    """
    if root == None:
        return 0
    # 若左子樹為空,則返回右子樹的深度,反之返回左子樹的深度
    if root.left == None :
        return minDepth(root.right) + 1
    if root.right == None:
        return minDepth(root.left) + 1
    #如果都不為空,則返回左子樹和右子樹深度的最小值
    leftDepth = minDepth(root.left) + 1
    rightDepth = minDepth(root.right) + 1
    return leftDepth if leftDepth < rightDepth else rightDepth

L1 = TreeNode(3)
L2 = TreeNode(9)
L3 = TreeNode(20)
L4 = TreeNode(15)
L5 = TreeNode(7)

L1.left = L2
L1.right = L3
L2.left = None
L2.right = None
L3.left = L4
L3.right = L5
res = minDepth(L1)
print(res)

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM