这是我对problem的解决方案,在给定二叉树的情况下,您要求查找所有非直接链接节点的总和。 "直接链接"是指亲子关系,只是为了清楚。
我的解决方案 如果访问了当前节点,则不允许您访问下一级别的节点。但是,如果未访问当前节点,则可能会访问或不访问下一级别的节点。
它通过了所有测试。但是,此递归二叉树遍历的运行时复杂性是什么。我认为它是2^n
因为,在每个节点,你有两个选择,无论是使用它还是不使用它,因此,下一个级别,对于这些选择中的每一个都有两个选择,等等。
空间复杂性:不使用任何额外的空间进行存储,但由于这是一个递归实现,因此使用堆栈空间,堆栈中的最大元素可以是树的高度,即n。所以O(n)
?
public int rob(TreeNode root) {
return rob(root, false);
}
public int rob(TreeNode root, boolean previousStateUsed) {
if(root == null)
return 0;
if(root.left == null && root.right == null)
{
if(previousStateUsed == true)
return 0;
return root.val;
}
if(previousStateUsed == true)
{
int leftSumIfCurrentIsNotUsedNotUsed = rob(root.left, false);
int rightSumIfCurrentIsNotUsed = rob(root.right, false);
return leftSumIfCurrentIsNotUsedNotUsed + rightSumIfCurrentIsNotUsed;
}
else
{
int leftSumIfCurrentIsNotUsedNotUsed = rob(root.left, false);
int rightSumIfCurrentIsNotUsed = rob(root.right, false);
int leftSumIsCurrentIsUsed = rob(root.left, true);
int rightSumIfCurrentIsUsed = rob(root.right, true);
return Math.max(leftSumIfCurrentIsNotUsedNotUsed + rightSumIfCurrentIsNotUsed, leftSumIsCurrentIsUsed + rightSumIfCurrentIsUsed + root.val);
}
}
答案 0 :(得分:1)
您当前的递归解决方案是O(2^n)
。很清楚,看看我们是否举了一个例子:
接下来,让我们划掉交替的节点层:
对于剩余的节点,我们有大约n/2
个节点(这会有所不同,但您总是可以删除交替的层以获得至少n/2 - 1
个节点的最坏情况。只有这些节点,我们可以将它们组合在一起,因为它们都没有冲突。因此,我们可以确定这至少需要Omega( 2^(n/2) )
次最坏情况。您可能会受到更严格的限制,但这应该会让您意识到您的解决方案无法很好地扩展。
这个问题是Max Non-Adajacent Sum Problem的常见修改。
您应该能够在此使用动态编程。我会极力推荐它。想象一下,我们正在为节点i
找到解决方案。假设我们已经有节点i.left
和i.right
的解决方案,我们也假设我们有他们的孩子(i
的孙子女)的解决方案。我们现在有i
最大解决方案的两个选项:
max-sum(i.left) + max-sum(i.right)
i.val + max-sum(i.left.left) + max-sum(i.left.right) + max-sum(i.right.left) + max-sum(i.right.right)
您最多使用这些,这是i
的解决方案。您可以在当前程序中执行此自下而上的DP或使用memoization。要么应该工作。最好的部分是,现在您的解决方案是O(n)
!