后续遍历框架的适用场景
很简单的思路,如果当前节点要做的事情需要通过左右⼦树的计算结果推导出来,就要⽤到后序遍历。
1373. 二叉搜索子树的最大键值和
解法:DFS 后序遍历
同样,按照管理,我们需要明确针对树中的每个节点「要做什么」以及「什么时候做」。根据二叉搜索树(BST)相关性质,我们确定「要做什么」,内容如下:
- 判断左子树和右子树是否为二叉搜索树
- 判断当前节点值是否大于左子树的最大值
- 判断当前节点值是否小于右子树的最小值
- 求解以当前节点为根节点的子树键值和
根据以上三点,站在当前节点的视⻆,需要知道以下具体信息:
- 左右⼦树是否是 BST。
- 左⼦树的最⼤值和右⼦树的最⼩值。
- 左右⼦树的节点值之和。
由于需要传递的信息超过1个,因此我们可以使用一个长度为4的整形数组来存储每个子树的返回值。
「什么时候做」:由于相关操作需要在得到左右子树的返回值后计算,因此采用后序遍历框架。
# 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:
# 全局变量用于存储最大键值和,初始化为0是为了针对题目中的示例3,即所有节点键值都为负数,返回0
maxSum = 0
def maxSumBST(self, root: Optional[TreeNode]) -> int:
self.traverse(root)
return self.maxSum
def traverse(self, node):
if not node:
# 叶子节点可视为单独的二叉搜索树,其左右子树都为空,因此要将子树最大值设置为负无穷,最小值设置为最小值,保证以该叶子节点为根节点的子树最大值和最小值都是它本身,体现25、26行。
return [1, float("-inf"), float("inf"), 0]
# 是否BST,子树最大值,子树最小值,子树键值和
left = self.traverse(node.left)
right = self.traverse(node.right)
# 判断以node为根节点子树是否为BST
if left[0] == 1 and right[0] == 1 and node.val > left[1] and node.val < right[2]:
sum_tree = left[3] + right[3] + node.val
max_value = max(right[1], node.val)
min_value = min(left[2], node.val)
self.maxSum = max(self.maxSum, sum_tree)
return [1, max_value, min_value, sum_tree]
else:
# 非BST,后三个位置数值后续不会用到,因此可以任意初始化,这里统一设置为0
return [0, 0, 0, 0]
1342. 将数字变为0的操作次数
解法:模拟
根据题意对相关操作进行模拟。
class Solution:
def numberOfSteps(self, num: int) -> int:
count = 0
while num != 0:
if num % 2 == 0:
num //= 2
else:
num -= 1
count += 1
return count