1, 二叉树最大深度(104)
二叉度有高度也有深度, 稍微区分一下二者. 深度是这个节点离根节点的距离, 可以理解成洞穴, 每往下一层就加1, 所以一般采取前序遍历, 即中左右的顺序, 往下遍历就加1. 高度是一个节点到叶子节点到距离, 可以理解成高楼, 一般采用后序遍历, 即左右中的顺序, 将叶子节点的高度返回给父节点, 父节点再做一个加1
这道题求二叉树的最大深度, 其实也就是根节点的高度, 所以采用后序遍历
首先确定递归函数的参数和返回值, 参数是这个树的根节点, 返回值就是深度. 然后确定终止条件, 即当node为空的时候返回值为0(指这个节点的高度为0)
最后确定单层循环的逻辑, 即取左右子树的最大高度并加1
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
return self.getdepth(root)
def getdepth(self, node):
if not node:
return 0
leftheight = self.getdepth(node.left)
rightheight = self.getdepth(node.right)
height = 1 + max(leftheight, rightheight)
return height
2. 二叉树的最小深度(111)
求二叉树的最小深度是求根节点到叶子节点最短距离, 也就是根节点的最小高度, 考虑用后序遍历来做. 从底向上计数.
这里和求最大深度有一点差别需要注意, 就是不能直接取左右子树最小值+1, 因为如果这样的话没办法保证是叶子节点. 很有可能根节点的左节点或者右节点就是空节点, 导致最小高度是1, 不符合题意
所以需要额外考虑根节点左边为空右边不为空, 和右边为空左边不为空两种情况
class Solution(object):
def minDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
return self.getdepth(root)
def getdepth(self, node):
if not node:
return 0
leftheight = self.getdepth(node.left)
rightheight = self.getdepth(node.right)
if node.left == None and node.right != None:
return 1+rightheight
if node.left != None and node.right == None:
return 1+leftheight
result = 1 + min(rightheight, leftheight)
return result
3. 完全二叉树的节点个数(222)
这道题要统计二叉树的节点个数, 首先按照普通的二叉树来写, 即遍历每个节点, 把左右节点的高度返回给上一个中间节点, 用后序遍历的顺序来写
class Solution(object):
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
return self.getdepth(root)
def getdepth(self, node):
if not node:
return 0
leftnum = self.getdepth(node.left)
rightnum = self.getdepth(node.right)
result = leftnum + rightnum + 1
return result
但是这个方法需要遍历每个节点, 时间复杂度高, 这道题给了是完全二叉树, 所以考虑有没有其他办法写, 完全二叉树的特征是除了底层节点, 上面的节点都是满的, 且底层节点是从左到右依次展开的
所以如果遍历到子树是满二叉树就可以直接用满二叉树的公式计算, 而判断满二叉树的方法是看往左遍历的深度和往右遍历的深度是否一样, 而是否是满二叉树是在确定返回条件这个步骤判断的
class Solution(object):
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
return self.getdepth(root)
def getdepth(self, node):
if not node:
return 0
left = node.left
right = node.right
leftdepth = 0
rightdepth = 0
while left:
left = left.left
leftdepth += 1
while right:
right = right.right
rightdepth += 1
if leftdepth == rightdepth:
return (2 << leftdepth) - 1
leftnum = self.getdepth(node.left)
rightnum = self.getdepth(node.right)
result = leftnum + rightnum + 1
return result
这是第一种判断left和right是否相等的方法, 即分别计算left和right外侧的深度, 看数值是否相等, 还有一种方法
while left and right:
count+=1
left = left.left; right = right.right
if not left and not right: # 如果同时到底说明是满二叉树,反之则不是
return 2**count-1
看left和right能否同时到底, 如果可以同时到底则是满二叉树, 否则就不是
我在想完全二叉树削掉最后一层不就是满二叉树了吗, 能不能单独计算叶子节点的数量, 再加上减去一层的满二叉树的节点数