110.平衡二叉树
思路:
递归三部曲:
- 参数和返回值:传入节点作为参数,返回树的高度
- 终止条件:因为要考虑只有单节点情况,所以终止条件应该是当节点为空,返回高度0
- 递归逻辑:计算左右子树的高度,如果高度差大于1则返回false,如果全满足小于等于1则返回True。为了提前终止递归,如果高度差大于1直接返回-1,遇到-1直接返回False
代码实现如下:
# 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: Optional[TreeNode]) -> bool:
if (height := self.getheight(root)) == -1:
return False
else:
return True
def getheight(self, node: Optional[TreeNode]) -> int:
if not node:
return 0
if (leftheight := self.getheight(node.left)) == -1: # 当有一个-1的时候就直接返回,提前终止递归,这里容易漏
return -1
if (rightheight := self.getheight(node.right)) == -1: # 当有一个-1的时候就直接返回,提前终止递归
return -1
if abs(leftheight - rightheight) > 1:
return -1
else:
return max(leftheight, rightheight) + 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 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 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.right:
st.append(node.right) # 右
if node.left:
st.append(node.left) # 左
else:
node = st.pop()
st.pop()
depth -= 1
result = max(result, depth)
return result
def isBalanced(self, root):
st = []
if root is None:
return True
st.append(root)
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
257. 二叉树的所有路径
思路:
递归三部曲:
- 参数和返回值:传入节点、记录路径的数组、结果数组作为参数。返回一个字符串数组。
- 终止条件:传入节点是叶子节点的时候,传入节点作为路径数组最后一个元素后压入结果数组。
- 递归逻辑:将当前节点压入路径数组后,将复制后的副本(为了回溯,否则要pop)传给下一个节点进行递归调用。
代码实现如下:
# 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 binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
result = []
self.getpath(root, [], result)
return result
def getpath(self, node: Optional[TreeNode], path: List, result: List[str]) -> None:
if not node.left and not node.right:
path.append(str(node.val))
string = "->".join(path)
result.append(string)
path.append(str(node.val))
if node.left:
self.getpath(node.left, path[:], result)
if node.right:
self.getpath(node.right, path[:], result)
规范代码:
# Definition for a binary tree node.class Solution:
def traversal(self, cur, path, result):
path.append(cur.val) # 中
if not cur.left and not cur.right: # 到达叶子节点
sPath = '->'.join(map(str, path))
result.append(sPath)
return
if cur.left: # 左
self.traversal(cur.left, path, result)
path.pop() # 回溯
if cur.right: # 右
self.traversal(cur.right, path, result)
path.pop() # 回溯
def binaryTreePaths(self, root):
result = []
path = []
if not root:
return result
self.traversal(root, path, result)
return result
迭代法:
class Solution:
def binaryTreePaths(self, root: TreeNode) -> List[str]:
# 题目中节点数至少为1
stack, path_st, result = [root], [str(root.val)], []
while stack:
cur = stack.pop()
path = path_st.pop()
# 如果当前节点为叶子节点,添加路径到结果中
if not (cur.left or cur.right):
result.append(path)
if cur.right:
stack.append(cur.right)
path_st.append(path + '->' + str(cur.right.val))
if cur.left:
stack.append(cur.left)
path_st.append(path + '->' + str(cur.left.val))
return result
404.左叶子之和
思路:
如果左孩子是叶子节点,则计入加和中,否则继续遍历寻找左叶子。
递归三部曲:
- 参数和返回值:参数是根节点,记录结果的数组。返回值是None。
- 终止条件:如果自身为空或者是叶子节点,返回。如果左孩子是叶子节点,计入加和后返回。
- 递归逻辑:对左右子树的左叶子进行加和。
代码实现如下:
# 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 sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
result = []
self.getleftleaves(root, result)
return sum(result)
def getleftleaves(self, node: Optional[TreeNode], result: List) -> None:
if not node:
return
if not node.left and not node.right:
return
if node.left and not node.left.left and not node.left.right: # 这里需要注意,一定需要node.left存在
result.append(node.left.val)
else:
self.getleftleaves(node.left, result)
self.getleftleaves(node.right, result)
规范代码:
# 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 sumOfLeftLeaves(self, root):
if root is None:
return 0
if root.left is None and root.right is None:
return 0
leftValue = self.sumOfLeftLeaves(root.left) # 左
if root.left and not root.left.left and not root.left.right: # 左子树是左叶子的情况
leftValue = root.left.val
rightValue = self.sumOfLeftLeaves(root.right) # 右
sum_val = leftValue + rightValue # 中
return sum_val
迭代法:
# 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 sumOfLeftLeaves(self, root):
if root is None:
return 0
st = [root]
result = 0
while st:
node = st.pop()
if node.left and node.left.left is None and node.left.right is None:
result += node.left.val
if node.right:
st.append(node.right)
if node.left:
st.append(node.left)
return result
222.完全二叉树的节点个数
思路:遍历一定能做,但是要理解满二叉树的节点算法:2^n - 1,利用这个特性,完全二叉树又一定可以由若干个满二叉树来组成,所以可以使用递归。
递归三部曲:
- 参数和返回值:参数是传入节点。返回值是int类型节点个数。
- 终止条件:当节点为空,分别返回0。
- 递归逻辑,寻找满二叉树同时记录深度n,利用2^n-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: Optional[TreeNode]) -> int:
if not root:
return 0
n = 1
left, right = root.left, root.right
while left and right:
n += 1
left = left.left
right = right.right
if left and right:
return 2 ** n - 1
return self.countNodes(root.left) + self.countNodes(root.right) + 1
规范代码,递归:
class Solution:
def countNodes(self, root: TreeNode) -> int:
return self.getNodesNum(root)
def getNodesNum(self, cur):
if not cur:
return 0
leftNum = self.getNodesNum(cur.left) #左
rightNum = self.getNodesNum(cur.right) #右
treeNum = leftNum + rightNum + 1 #中
return treeNum
迭代法:
import collections
class Solution:
def countNodes(self, root: TreeNode) -> int:
queue = collections.deque()
if root:
queue.append(root)
result = 0
while queue:
size = len(queue)
for i in range(size):
node = queue.popleft()
result += 1 #记录节点数量
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
完全二叉树:
class Solution:
def countNodes(self, root: TreeNode) -> int:
if not root:
return 0
left = root.left
right = root.right
leftDepth = 0 #这里初始为0是有目的的,为了下面求指数方便
rightDepth = 0
while left: #求左子树深度
left = left.left
leftDepth += 1
while right: #求右子树深度
right = right.right
rightDepth += 1
if leftDepth == rightDepth:
return (2 << leftDepth) - 1 #注意(2<<1) 相当于2^2,所以leftDepth初始为0
return self.countNodes(root.left) + self.countNodes(root.right) + 1