一、最大深度
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)