时间复杂度:O(n)
解题思路
后序遍历。
对于每个结点都有被打劫和不被打劫两种选择,如果被打劫,那么它的父节点和孩子一定不能被打劫,但如果不被打劫,它的父亲和孩子不一定会被打劫。
所以用后序遍历的方法让孩子告诉父节点,如果孩子被打劫和不被打劫的收益分别是多少,然后父节点如果被打劫那么收益就是自身的结点值和俩孩子不被打劫的收益之和,如果父节点不被打劫,那么收益就是左孩子的最大收益和右孩子的最大收益之和。
AC代码
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rob(root *TreeNode) int {
var postOrder func(*TreeNode)(a,b int)
postOrder=func(root *TreeNode)(a,b int){
if root==nil{
return 0,0
}
l1,l2:=postOrder(root.Left)
r1,r2:=postOrder(root.Right)
a=max(l1,l2)+max(r1,r2)//不抢劫root结点
b=root.Val+l1+r1//抢劫root结点
return a,b
}
return max(postOrder(root))
}
func max(a,b int)int{
if a>b{
return a
}
return b
}
感悟
后序遍历真的是yyds,好多涉及到在递归过程中解决的问题都可以考虑后序遍历的方法。