代码随想录 day16 第六章 二叉树part03

今日内容:

●  104.二叉树的最大深度  559.n叉树的最大深度

●  111.二叉树的最小深度

●  222.完全二叉树的节点个数

迭代法,大家可以直接过,二刷有精力的时候 再去掌握迭代法。

1. 二叉树的最大深度 (优先掌握递归)

关联 leetcode 104.二叉树的最大深度

  • 定义

    • 叶子节点:
      • 没有子节点的节点
    • 深度:
      • 【把根节点看作地表,下面的节点都是深埋的树根,每一层树根埋的深度】
      • 任意一个节点到根节点的距离
        • 自身节点算一个度,第二层节点深度是 2
        • 根节点的深度是1
      • 求解方式:
        • 从上往下计数
          • 从根节点往下走到目标节点
          • 根节点初始深度:1,往下走一次 +1
        • 前序遍历
    • 高度:
      • 【把二叉树反过来看,叶子节点代表树冠,整棵树的高度】
      • 二叉树中任意一个节点到叶子节点的距离
        • 假设有一颗3层满二叉树,
          • 根节点的高度:3
          • 第二层节点的高度:2
          • 叶子节点高度:1
      • 求解方式
        • 从下往上计数
          • 从叶子节点往上走到目标节点
          • 父节点知道子节点【例如叶子节点的高度】+本层的 高度1 就行
        • 后序遍历
  • 题解

    • 最大深度 == 根节点的高度
    func getHeight(node *TreeNode) int {
    	if node == nil {
    		return 0
    	}
    	//	左孩子高度
    	leftHeight := getHeight(node.Left)
    	//	右孩子高度
    	rightHeight := getHeight(node.Right)
    	//	当前节点高度
    	height := 1 + max(leftHeight, rightHeight)
    	return height
    }
    func maxDepth(root *TreeNode) int {
    	return getHeight(root)
    }
    

2. 二叉树的最小深度 (优先掌握递归)

关联 leetcode 111.二叉树的最小深度

  • 二叉树的最小深度
    • 最小深度是从根节点到最近叶子节点的最短路径上的节点数量
      • 叶子节点:左右孩子都为空
  • 补充定义
    • 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
    • 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数后者节点数(取决于高度从0开始还是从1开始)
  • 题解
    • 使用后序遍历

      • 其实求的是根节点到叶子节点的最小距离,就是求高度的过程,不过这个最小距离 也同样是最小深度
    • 递归

      func getDepth(node *TreeNode) int {
      	if node == nil {
      		return 0
      	}
      	leftDepth := getDepth(node.Left)
      	rightDepth := getDepth(node.Right)
      	if node.Left == nil && node.Right != nil {
      		return 1 + rightDepth
      	}
      	if node.Right == nil && node.Left != nil {
      		return 1 + leftDepth
      	}
      	depth := 1 + min(leftDepth, rightDepth)
      	return depth
      }
      func minDepth(root *TreeNode) int {
      	return getDepth(root)
      }
      

2. 完全二叉树的节点个数(优先掌握递归)

关联 leetcode 222.完全二叉树的节点个数

  • 统计节点数量
    • 普通二叉树

      • 所有处理节点都是当前遍历到的节点【可以抽象的看作都是中间节点】

      • 递归

        //闭包实现
        func countNodes(root *TreeNode) int {
        
        	if root == nil {
        		return 0
        	}
        	res := 0
        	var loopNode func(node *TreeNode) int
        	loopNode = func(node *TreeNode) int {
        		if node == nil {
        			return 0
        		}
        		
        		//前序遍历, 中后序同理
        		res += 1
        		loopNode(node.Left)
        		loopNode(node.Right)
        
        		return res
        	}
        	loopNode(root)
        	return res
        }
        
        // 实现2
        func countNodes(root *TreeNode) int {
        	if root == nil {
        		return 0
        	}
        
        	var loopNode func(node *TreeNode) int
        	loopNode = func(node *TreeNode) int {
        		if node == nil {
        			return 0
        		}
        		//前序遍历, 中后序同理
        		leftSonSum := loopNode(node.Left)
        		rightSonSum := loopNode(node.Right)
        		nodesSum := 1 + leftSonSum + rightSonSum //当前节点+左右子树的节点数量
        		return nodesSum
        	}
        
        	return loopNode(root)
        }
        
      • 层序遍历

        func countNodes(root *TreeNode) int {
        	if root == nil {
        		return 0
        	}
        	res := 0
        	nodes := make([]*TreeNode, 0)
        	nodes = append(nodes, root)
        	for len(nodes) > 0 {
        		node := nodes[len(nodes)-1]
        		if node != nil {
        			res += 1
        		}
        		nodes = nodes[:len(nodes)-1]
        		if node.Left != nil {
        			nodes = append(nodes, node.Left)
        		}
        		if node.Right != nil {
        			nodes = append(nodes, node.Right)
        		}
        	}
        	return res
        }
        
    • 完全二叉树

      • 除了底层节点,上面的每层都是满节点
      • 底层节点从左到右依次填满
  • 题解
    • 普通二叉树做法

      • 递归

        //闭包实现
        func countNodes(root *TreeNode) int {
        
        	if root == nil {
        		return 0
        	}
        	res := 0
        	var loopNode func(node *TreeNode) int
        	loopNode = func(node *TreeNode) int {
        		if node == nil {
        			return 0
        		}
        		
        		//前序遍历, 中后序同理
        		res += 1
        		loopNode(node.Left)
        		loopNode(node.Right)
        
        		return res
        	}
        	loopNode(root)
        	return res
        }
        
        // 实现2
        func countNodes(root *TreeNode) int {
        	if root == nil {
        		return 0
        	}
        
        	var loopNode func(node *TreeNode) int
        	loopNode = func(node *TreeNode) int {
        		if node == nil {
        			return 0
        		}
        		//前序遍历, 中后序同理
        		leftSonSum := loopNode(node.Left)
        		rightSonSum := loopNode(node.Right)
        		nodesSum := 1 + leftSonSum + rightSonSum //当前节点+左右子树的节点数量
        		return nodesSum
        	}
        
        	return loopNode(root)
        }
        
      • 层序遍历

        func countNodes(root *TreeNode) int {
        	if root == nil {
        		return 0
        	}
        	res := 0
        	nodes := make([]*TreeNode, 0)
        	nodes = append(nodes, root)
        	for len(nodes) > 0 {
        		node := nodes[len(nodes)-1]
        		if node != nil {
        			res += 1
        		}
        		nodes = nodes[:len(nodes)-1]
        		if node.Left != nil {
        			nodes = append(nodes, node.Left)
        		}
        		if node.Right != nil {
        			nodes = append(nodes, node.Right)
        		}
        	}
        	return res
        }
        
    • 完全二叉树做法

      • 如果左右子树分别向左右遍历的得到的深度一致
        • 子树的外侧长度一致
        • 从该节点往下到叶子节点是一棵满二叉树
          • 节点数量:
            • 2^depth-1
      • 题解

        func countNodes(root *TreeNode) int {
        	if root == nil {
        		return 0
        	}
        	leftSon := root.Left
        	rightSon := root.Right
        	leftDepth, rightDepth := 0, 0
        	for leftSon != nil {
        		leftSon = leftSon.Left
        		leftDepth++
        	}
        	for rightSon != nil {
        		rightSon = rightSon.Right
        		rightDepth++
        	}
        	//整棵树是满二叉树
        	if leftDepth == rightDepth {
        		return (2 << leftDepth) - 1 // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
        	}
        	//这个棵树不是满二叉树: 计算 根节点+左子树节点数+右子树节点数
        	return 1 + countNodes(root.Left) + countNodes(root.Right)
        }
        

  • 14
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值