337、打家劫舍3
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。
除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
示例1:
输入: root = [3,2,3,null,3,null,1]
输出: 7
解释: 小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7
示例2:
输入: root = [3,4,5,1,3,null,1]
输出: 9
解释: 小偷一晚能够盗取的最高金额 4 + 5 = 9
思路:
对于一个节点,有选择或不选两种情况,而对于选择来说,依赖于左右子树的情况,如果左右子树已经选择,那么这个节点不能进行选择。所以每个节点的最大收益应该是根据子节点来进行选择或者不选择的。
class Solution:
def rob(self, root: TreeNode) -> int:
# 返回当前节点选择和不选择的最高金额
def dfs(root):
if not root: return 0, 0
ls, ln = dfs(root.left)
rs, rn = dfs(root.right)
# 如果当前节点选择,那么子节点应该不能被选择
s = root.val + ln + rn
# 如果当前节点不选择,那么取子节点选择与不选择的最大值即可
n = max(ls, ln) + max(rs, rn)
return s, n
# 最终得到选择和不选择的结果,此时返回最大值即可
s, n = dfs(root)
return max(s, n)
988、从叶节点开始的最小字符串
给定一颗根结点为 root 的二叉树,树中的每一个结点都有一个 [0, 25] 范围内的值,分别代表字母 ‘a’ 到 ‘z’。
返回 按字典序最小 的字符串,该字符串从这棵树的一个叶结点开始,到根结点结束。
注:字符串中任何较短的前缀在 字典序上 都是 较小 的:
- 例如,在字典序上 “ab” 比 “aba” 要小。叶结点是指没有子结点的结点。
节点的叶节点是没有子节点的节点。
示例1:
输入:root = [0,1,2,3,4,3,4]
输出:"dba"
示例2:
输入:root = [25,1,3,1,3,0,2]
输出:"adz"
示例3:
输入:root = [2,2,1,null,1,0,null,0]
输出:"abc"
思路:
通过递归可以得出从根节点到叶子节点的字符串,然后判断当前结点是否是叶子结点,如果是叶子结点进行字符串的更新
注意这里的树给出的是0~25的数字,转换成字符串应该+97然后再进行转换即可
class Solution:
def smallestFromLeaf(self, root: Optional[TreeNode]) -> str:
self.ans = ""
# 迭代过程中将该节点的字符串传递下去
def dfs(root, prestr):
if not root: return
# 将当前结点转换成字符串
rootCh = chr(root.val + 97)
# 生成当前字符串
curStr = f"{rootCh}{prestr}"
# 如果当前结点是叶子结点,需要更新最短字符串
if not root.left and not root.right:
if not self.ans: self.ans = curStr
else: self.ans = min(self.ans, curStr)
return
dfs(root.left, curStr)
dfs(root.right, curStr)
dfs(root, "")
return self.ans