题目

26年7月17日(首刷看解)
Go
func rob(root *TreeNode) int {
steal,notsteal:=dfs(root)
return max(steal,notsteal)
}
func dfs(root *TreeNode)(int ,int){
if root==nil{
return 0,0
}
leftsteal,leftnotsteal:=dfs(root.Left)
rightsteal,rightnotsteal:=dfs(root.Right)
cursteal:=root.Val+leftnotsteal+rightnotsteal
curnotsteal:=max(leftsteal,leftnotsteal)+max(rightsteal,rightnotsteal)
return cursteal,curnotsteal
}
思路
这道题我一开始想到的就是之前做过那道安摄像头的题,想到用flag标记隔层,
大概就是这样 (错误的)
Go
func rob(root *TreeNode) int {
res1:=dfs(root,0,0)
res2:=dfs(root,1,0)
return max(res1,res2)
}
func dfs(root *TreeNode,flag int,total int) int{
if root==nil{
return 0
}
if flag==1{
total+=root.Val
total+=dfs(root.Left,0,total)
total+=dfs(root.Right,0,total)
}else{
total+=dfs(root.Left,1,total)
total+=dfs(root.Right,1,total)
}
return total
}
其实怎么说呢,我这里问题主要有total值作为参数传串了,左子树和右子树应该是独立的计算不能干扰 ,然后错误的点就是如果父节点没偷,相当于子节点就必偷了,其实也有父节点没偷,子节点也不偷才是金额最大的情况。比如3-1-2-3,模拟四层,偷第一层和最后一层才是最多的。
所以前序遍历就是错的,后序遍历才是对的,其实如果父亲没偷,就是找子节点偷和不偷的最大值,如果父亲偷了,就是找子节点没偷的最大值,是建立在先知道子节点的最大收益上的,所以选择后序遍历,
第一个就是遍历顺序 ,第二个就是返回值
这道题还有一个关键就是想到有两个返回值,分别代表偷和没偷,我几乎没遇到过这种情况,原来可以两个返回值,
然后剩下的就是把递归的三部+结合后序遍历模版,写代码了