110. 平衡二叉树
题目:给定一个二叉树,判断它是否是 平衡二叉树
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: true
示例 2:
输入: root = [1,2,2,3,3,null,null,4,4]
输出: false
解题思路
如果节点为空,返回 0。 递归计算左右子树的高度,存储在 left 和 right 变量中。 如果左右子树的高度差大于 1,或者左右子树有一个不平衡,则返回 -1。 否则,返回左右子树高度的最大值加 1。
- 时间复杂度:O(n)
- 空间复杂度:O(h)
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
return self.getHight(root) != -1
def getHight(self, root):
if not root:
return 0
left_hight = self.getHight(root.left)
right_hight = self.getHight(root.right)
# 如果左右子树其中一棵不平衡,或者左右子树的高度差>1,非平衡
if left_hight == -1 or right_hight == -1 or abs(left_hight- right_hight) > 1:
return -1
return max(left_hight, right_hight) + 1
总结
这道题目考察了二叉树的遍历和递归思想。通过递归计算每个节点的左右子树高度,并判断是否满足平衡二叉树的条件,从而得出最终的结果。这种自底向上的递归方式,可以很好地解决这类需要从子问题推导出父问题的题目。
257. 二叉树的所有路径
题目:给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入: root = [1,2,3,null,5]
输出: ["1->2->5","1->3"]
解题思路
回溯,使用track数组记录当前路径的节点值,进入节点时加入值,离开节点时候删除值。遇到叶子节点时候将当前路径加入到result。
- 时间复杂度:O(n^2)
- 空间复杂度:O(n^2)
class Solution:
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
self.result = []
track = []
self.traverse(root, track)
return self.result
def traverse(self, root, track = []):
if not root:
return
# 前序位置加入节点
track.append(str(root.val))
if not root.left and not root.right:
self.result.append("->".join(track))
self.traverse(root.left, track)
self.traverse(root.right, track)
# 后续位置删除节点
track.pop()
404. 左叶子之和
题目:给定二叉树的根节点 root ,返回所有左叶子之和。
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:
输入: root = [1]
输出: 0
解题思路
- 时间复杂度:O()
- 空间复杂度:O()
class Solution:
def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
self.results = [0] # 记录左叶子值
self.traverse(root, is_left=False)
return sum(self.results)
def traverse(self, root, is_left = False):
if not root:
return
# 前序位置进入节点做处理
if not root.left and not root.right and is_left:
self.results.append(root.val)
self.traverse(root.left, is_left=True)
self.traverse(root.right, is_left=False)
222. 完全二叉树的节点个数
题目:给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
示例 1:
输入: root = [1,2,3,4,5,6]
输出: 6
解题思路1:层次遍历
完全二叉树指除了底层其他每一层节点数量达到最大值,底层左边是满的,高度为h数量为1~2^h -1
- 时间复杂度:O(n)
- 空间复杂度:O(n)
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
queue = [root]
result = 0
while queue:
size = len(queue)
for _ in range(size):
node = queue.pop(0)
result += 1
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
解题思路2:递归
- 时间复杂度:O(n)
- 空间复杂度:O(logn),算上了递归系统栈占用的空间
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
return 1 + self.countNodes(root.left) + self.countNodes(root.right)
解题思路3:递归时考虑满二叉树
- 时间复杂度:O(lognxlogn)
- 空间复杂度:O(logn)
# 讨论满二叉树的情况
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
pl, pr = root, root # pl往左遍历 pr往右遍历
nl, nr = 0, 0 # nl,nr分别记录左右子树的高度
while pl:
pl = pl.left
nl += 1
while pr:
pr = pr.right
nr += 1
if nl == nr:
return 2**nl - 1
return 1 + self.countNodes(root.left) + self.countNodes(root.right)