Leetcode 222 完全二叉树的节点个数
题目:
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~
2
h
2^h
2h 个节点。
示例 1:
输入:root = [1,2,3,4,5,6]
输出:6
示例 2:
输入:root = []
输出:0
示例 3:
输入:root = [1]
输出:1
提示:
- 树中节点的数目范围是[0, 5 * 1 0 4 10^4 104]
- 0 <= Node.val <= 5 * 1 0 4 10^4 104
- 题目数据保证输入的树是 完全二叉树
算法思想:
本题要明确以下几点:
- 什么是完全二叉树:一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
- 完全二叉树的性质:除了最后一层的叶子结点外,其余n层的节点数量为 2 n − 1 2^n-1 2n−1,因此可以借助性质解决这个问题。
本题第一种思路是使用普通树的遍历方式,包括递归法和迭代法。第二种是使用完全二叉树的性质,递归方式。
代码实现:
第一种方式:利用普通二叉树的方式
(1)递归法
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def countNodes(self, root) -> int:
return self.getNodeNums(root)
def getNodeNums(self, root):
if not root:
return 0
leftNums = self.getNodeNums(root.left)
rightNums = self.getNodeNums(root.right)
nodeNums = leftNums + rightNums + 1
return nodeNums
(2)迭代法
import collections
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def countNodes(self, root) -> int:
if not root:
return 0
queue = collections.deque([root])
result = 0
while queue:
for _ in range(len(queue)):
node = queue.pop()
result += 1
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
第二种方式:完全利用完全二叉树的性质
思想:从题目中得知,输入数据会保证是完全二叉树,那么分别从左右两侧遍历到叶子结点,如果深度相同,那就是完全二叉树,否则继续递归到子节点,继续判断,以此类推。以下代码基于这种思想实现。
# 定义树结构
class TreeNode:
def __init__(self, val=0, left=None, right=None) -> None:
self.val = val
self.left = left
self.right = right
class Solution:
def countNodes(self, root) -> int:
if not root:
return 0
left = root.left
right = root.right
depth_l = depth_r = 0
while left:
depth_l += 1
left = left.left
while right:
depth_r += 1
right = right.right
if depth_l == depth_r:
return (2 << depth_l) - 1
return self.countNodes(root.left) + self.countNodes(root.right) + 1
Leetcode 110 平衡二叉树
题目:
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:true
示例 2:
输入:root = [1,2,2,3,3,null,null,4,4]
输出:false
示例 3:
输入:root = []
输出:true
提示:
- 树中的节点数在范围 [0, 5000] 内
- - 1 0 4 10^4 104 <= Node.val <= 1 0 4 10^4 104
算法思想:
递归法与求二叉树的最大深度类似,具体参见博客 或Leetcode 104。具体来说,递归遍历左子树的高度,递归遍历右子树的高度,作差,如果绝对值大于1,说明不是平衡二叉树,否则是平衡二叉树。但不同的地方在于,在求最大深度的题目中,每次的返回是当前节点的最大深度,而在本题中,返回值前要判断左右子树的高度差是否大于1,如果大于1,返回-1表示非平衡二叉树;如果小于1,正常返回当前节点的高度,最后判断返回值是否是-1 确定是否是平衡二叉树。
非递归法利用栈的思想。在主函数中循环调用,每调用一次,判断左右子树的高度差是否大于1。在求高度的函数中,在当前层的节点后加入None,以确保当前层的节点结束;另外,depth随着进出栈的不同而不断变化,这样才能保证所求的是正确的深度。
代码实现:
- 递归法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
if self.get_height(root) != -1:
return True
else:
return False
def get_height(self, root: TreeNode) -> int:
# Base Case
if not root:
return 0
# 左
if (left_height := self.get_height(root.left)) == -1:
return -1
# 右
if (right_height := self.get_height(root.right)) == -1:
return -1
# 中
if abs(left_height - right_height) > 1:
return -1
else:
return 1 + max(left_height, right_height)
- 迭代法
# 定义树节点结构
class TreeNode:
def __init__(self, val=0, left=None, right=None) -> None:
self.val = val
self.left = left
self.right = right
class Solution:
def getDepth(self, cur):
st = []
if cur is not None:
st.append(cur)
depth = 0
result = 0
while st:
node = st[-1]
if node is not None:
st.pop()
st.append(node)
st.append(None)
depth += 1
if node.left:
st.append(node.left)
if node.right:
st.append(node.right)
else:
node = st.pop()
st.pop()
depth -= 1
result = max(result, depth)
def isBalanced(self, root):
st = []
if root is not None:
st.append(root)
else:
return True
while st:
node = st.pop()
if abs(self.getDepth(node.left)-self.getDepth(node.right)) > 1:
return False
if node.right:
st.append(node.right)
if node.left:
st.append(node.left)
return True
import unittest
class TestSolution(unittest.TestCase):
def test_isBalanced(self):
# Test case 1
root1 = TreeNode(3)
root1.left = TreeNode(9)
root1.right = TreeNode(20)
root1.right.left = TreeNode(15)
root1.right.right = TreeNode(7)
solution = Solution()
self.assertTrue(solution.isBalanced(root1))
if __name__ == '__main__':
unittest.main()