zoukankan      html  css  js  c++  java
  • 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)
    

      

  • 相关阅读:
    英文半字节压缩编码技术
    博弈翻硬币游戏
    POJ 2015 Permutation Code
    8051、ARM和DSP指令周期的测试与分析
    Huffman编码
    CentOS 命令提示符颜色及样式详解
    JAVA程序员面试32问
    面向抽象编程:接口和抽象类
    初学实用:实例讲解Java中的接口的作用
    C#和Java的区别
  • 原文地址:https://www.cnblogs.com/nxf-rabbit75/p/11675906.html
Copyright © 2011-2022 走看看