104.二叉树的最大深度
- 二叉树节点的深度:任意一个节点到根节点的距离(取决于深度从0开始还是从1开始)
- 二叉树节点的高度:指从节点到叶子节点( 叶子节点是指没有子节点的节点)的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始),(叶子节点的高度返回给其父节点,父节点在叶子节点的高度上加一就是父节点的高度,所以先处理子节点,最后处理父节点,就是左右中的顺序,即后序遍历)
例如:上面这棵二叉树,根节点的3的深度是1,节点9和20的深度是2,节点15和7的深度是3;
根节点3的高度是3,节点9和20的高度是2,节点15和7的高度是1.
前序遍历求深度,后序遍历求高度,而根节点的高度就是二叉树的最大深度,所以可以通过后序求的根节点高度来求的二叉树最大深度。
后序遍历(左右中)来计算树的高度:
- 确定递归函数的参数和返回值:参数就是传入树的根节点,返回就返回这棵树的深度。
- 确定终止条件:如果为空节点的话,就返回0,表示高度为0。
- 确定单层递归的逻辑:先求它的左子树的深度,再求右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度
class TreeNode(object):
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution(object):
def maxDepth(self, root):
return self.getheight(root)
def getheight(self,node):
if not node:
return 0
leftheight=self.getheight(node.left)
rightheight=self.getheight(node.right)
height=1+max(leftheight,rightheight)
return height
559.n叉树的最大深度
给定一个 n 叉树,找到其最大深度。
最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。
class Node(object):
def __init__(self, val=None, children=None):
self.val = val
self.children = children
class Solution(object):
def maxDepth(self, root):
if not root: #如果根节点为空,则深度为0
return 0
maxheight=1
for child in root.children:
childheight=self.maxDepth(child) #递归调用maxDepth函数求出每个子节点的深度
maxheight=max(maxheight,childheight+1)#更新最大深度
return maxheight
111.二叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量
例:
返回它的最小深度 2
那么通过后序遍历求根节点的最小高度其实就求出了二叉树的最小深度
递归:
- 确定递归函数的参数和返回值:参数为要传入的二叉树根节点,返回的是
- 确定终止条件:遇到空节点返回0,表示当前节点的高度为0
- 确定单层递归的逻辑
这块和求最大深度可就不一样了,如果写成以下代码:
leftDepth = getDepth(node.left)
rightDepth = getDepth(node.right)
result = 1 + min(leftDepth, rightDepth)
return result
就会出现以下错误:
如果这么求的话,没有左孩子的分支会算为最短深度
所以应该加上以下逻辑专门处理这种情况:
如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。 最后如果左右子树都不为空,返回左右子树深度最小值 + 1
class TreeNode(object):
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution(object):
def minDepth(self, root):
if not root:
return 0
leftheight=self.minDepth(root.left)
rightheight=self.minDepth(root.right)
# 当一个左子树为空,右不为空,这时并不是最低点
if root.left is None and root.right is not None:
result=1+rightheight
# 当一个右子树为空,左不为空,这时并不是最低点
elif root.left is not None and root.right is None:
result=1+leftheight
# 左右子树都不为空时:
else:
result=1+min(leftheight,rightheight)
return result
222.完全二叉树的节点个数
给你一棵 完全二叉树 的根节点 root
,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h
层,则该层包含 1~ 个节点
普通二叉树求节点数量:
class TreeNode(object):
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution(object):
def countNodes(self, root):
if not root:
return 0
left=self.countNodes(root.left) # 左子树节点数量
right=self.countNodes(root.right) # 右子树节点数量
result=1+left+right # 整个二叉树节点数量=左+右+1
return result
利用完全二叉树的性质求节点数量:
完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
对于情况二,分别递归左孩子和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算
如何去判断一个左子树或者右子树是不是满二叉树呢?
在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树。如图:
在完全二叉树中,如果递归向左遍历的深度不等于递归向右遍历的深度,则说明不是满二叉树,如图:
class TreeNode(object):
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution(object):
def countNodes(self, root):
if not root:
return 0
left=root.left
right=root.right
leftdeep=1
rightdeep=1 #根节点的左右子树深度为1
while(left):
left=left.left
leftdeep+=1
while(right):
right=right.right
rightdeep+=1
if leftdeep==rightdeep:
# 如果左子树和右子树深度相同,说明是满二叉树,利用公式计算节点数量
return 2**(leftdeep)-1 #根节点深度为1
else: # 如果深度不相同就递归计算左右子树节点数量
return 1+self.countNodes(root.left)+self.countNodes(root.right)