文章目录
687、最长同值路径
给定一个二叉树的 root ,返回 最长的路径的长度 ,这个路径中的 每个节点具有相同值 。 这条路径可以经过也可以不经过根节点。
两个节点之间的路径长度 由它们之间的边数表示。
示例1:
输入:root = [5,4,5,1,1,5]
输出:2
示例2:
输入:root = [1,4,5,4,4,5]
输出:2
思路:
对于树这种找路径的题,一般使用递归来做,假设左,右子树已经处理好,这个时候到了当前节点,那么怎么计算出所要的结果,也就是当前的逻辑。
对于当前节点来说,最长路径应该是左右子树路径的最大值,如果左右节点的值和当前结点一致,那么就应该在路径上+1
那么对于整棵树来说,最长路径应该是左子树的路径,右子树的路径或者左右子树的加和(如果根节点和左右子树值一样),或者是之前已经存储的最大值
class Solution:
def longestUnivaluePath(self, root: TreeNode) -> int:
self.ans = 0
def dfs(root):
if not root: return 0
left_length = dfs(root.left)
right_length = dfs(root.right)
left, right = 0, 0
# 如果根节点的值等于左节点的值,那么左节点的值为左子树最大值+1,否则为0
# 因为如果不等,那么之前的最大值已经缓存,所以对于当前节点来说,左子树的长度就只有当前节点一个节点,那么就是0
if root.left and root.val == root.left.val:
left = left_length + 1
if root.right and root.val == root.right.val:
right = right_length + 1
# 缓存最大长度的路径
self.ans = max(self.ans, left + right)
# 返回当前结点的最大值
return max(left, right)
dfs(root)
return self.ans
979、在二叉树中分配硬币
给定一个有 N 个结点的二叉树的根结点 root,树中的每个结点上都对应有 node.val 枚硬币,并且总共有 N 枚硬币。
在一次移动中,我们可以选择两个相邻的结点,然后将一枚硬币从其中一个结点移动到另一个结点。(移动可以是从父结点到子结点,或者从子结点移动到父结点。)。
返回使每个结点上只有一枚硬币所需的移动次数。
示例1:
输入:[3,0,0]
输出:2
解释:从树的根结点开始,我们将一枚硬币移到它的左子结点上,一枚硬币移到它的右子结点上。
示例2:
输入:[0,3,0]
输出:3
解释:从根结点的左子结点开始,我们将两枚硬币移到根结点上 [移动两次]。然后,我们把一枚硬币从根结点移到右子结点上。
示例3:
输入:[1,0,2]
输出:2
示例4:
输入:[1,0,0,null,3]
输出:4
思路:
移动金币有三种情况,一种是结点只有一个金币,那就不需要金币,如果结点为0,需要从父节点移动一个金币给自己,如果该节点有n个金币,那么需要将n-1个金币移走。
那么对于节点来说,要么要么把金币移走,要么把金币移过来,如果考虑根节点,那么就好像借位一样,不管怎么移动,都是需要通过父节点操作,那么如果需要移走n个金币,那就在父节点记+n,如果需要借n个金币,那就在父节点记-n金币,至于父节点怎么处理,对于子节点来说是不需要了解其细节的。
class Solution:
def distributeCoins(self, root: Optional[TreeNode]) -> int:
self.ans = 0
def dfs(root):
if not root: return 0
left = dfs(root.left)
right = dfs(root.right)
# 左右节点的移动可能是负的,加到结果即可
self.ans += abs(left) + abs(right)
# 这里当前结点需要移动的数量为 当前结点本身拥有的数量 + 左右子树要移动的数量 - 当前结点应该保留一个金币
return root.val + left + right - 1
dfs(root)
return self.ans
1026、节点与其祖先之间的最大值
给定二叉树的根节点 root,找出存在于 不同 节点 A 和 B 之间的最大值 V,其中 V = |A.val - B.val|,且 A 是 B 的祖先。
(如果 A 的任何子节点之一为 B,或者 A 的任何子节点是 B 的祖先,那么我们认为 A 是 B 的祖先)
示例1:
输入:root = [8,3,10,1,6,null,14,null,null,4,7,13]
输出:7
示例2:
输入:root = [1,null,2,null,0,3]
输出:3
思路:
需要求节点与其祖先的最大值,由于这里的最大值是绝对值,所以不能单纯的认为祖先的值大于子节点的值,在做比较的时候需要和整个父节点的最小值和最大值进行比较,这样才能获得最大差值
class Solution:
def maxAncestorDiff(self, root: Optional[TreeNode]) -> int:
self.ans = 0
# 递归的时候传入祖父结点的最大值和最小值
def dfs(root, smallest, largest):
if not root:return
# 取该节点与最大值和最小值的差值,在与已经缓存的结果进行比较
self.ans = max(self.ans, max(abs(smallest - root.val), abs(largest - root.val)))
# 动态更新最小值和最大值
smallest = min(root.val, smallest)
largest = max(root.val, largest)
# 递归左子树和右子树
dfs(root.left, smallest, largest)
dfs(root.right, smallest, largest)
if not root: return 0
dfs(root, root.val, root.val)
return self.ans