Algorithm 递归二叉树遍历的运行时复杂性
这是我的解决方案,给定一棵二叉树,你需要找到所有非直接链接节点的总和。“直接联系”是指亲子关系,这一点很清楚 我的解决方案 如果访问了当前节点,则不允许您访问下一级别的节点。但是,如果未访问当前节点,则您可以访问下一级别的节点,也可以不访问下一级别的节点 它通过了所有的测试。但是,这种递归二叉树遍历的运行时复杂性是多少。我认为这是Algorithm 递归二叉树遍历的运行时复杂性,algorithm,recursion,time-complexity,binary-tree,big-o,Algorithm,Recursion,Time Complexity,Binary Tree,Big O,这是我的解决方案,给定一棵二叉树,你需要找到所有非直接链接节点的总和。“直接联系”是指亲子关系,这一点很清楚 我的解决方案 如果访问了当前节点,则不允许您访问下一级别的节点。但是,如果未访问当前节点,则您可以访问下一级别的节点,也可以不访问下一级别的节点 它通过了所有的测试。但是,这种递归二叉树遍历的运行时复杂性是多少。我认为这是2^n,因为在每个节点上,您都有两个选择,是否使用它,以及相应地,下一个级别,每个选择都有两个选择,依此类推 空间复杂性:不使用任何额外的存储空间,但由于这是一个递归实
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);
}
}
您当前的递归解决方案将是
O(2^n)
。很明显,我们可以举一个例子:
接下来,让我们划掉交替的节点层:
对于剩余的节点,我们有大约n/2
节点(这会有所不同,但在最坏的情况下,您始终可以删除交替层以获得至少n/2-1
节点)。仅使用这些节点,我们就可以对它们进行任意组合,因为它们之间没有冲突。因此,我们可以确定,在最坏的情况下,这至少需要Omega(2^(n/2))
时间。您可能会得到一个更严格的界限,但这会让您意识到您的解决方案无法很好地扩展
这个问题是一个非常常见的问题
您应该能够在这方面使用动态规划。我强烈推荐它。假设我们正在为nodei
找到解决方案。假设我们已经有了节点i.left
和i.right
的解决方案,还假设我们有了它们的子节点(i
的孙子节点)的解决方案。对于i
的max解决方案,我们现在有两个选项:
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或使用备忘录。两者都应该有效。最好的部分是,现在您的解决方案是O(n)
您当前的递归解决方案将是O(2^n)
。很明显,我们可以举一个例子:
接下来,让我们划掉交替的节点层:
对于剩余的节点,我们有大约n/2
节点(这会有所不同,但在最坏的情况下,您始终可以删除交替层以获得至少n/2-1
节点)。仅使用这些节点,我们就可以对它们进行任意组合,因为它们之间没有冲突。因此,我们可以确定,在最坏的情况下,这至少需要Omega(2^(n/2))
时间。您可能会得到一个更严格的界限,但这会让您意识到您的解决方案无法很好地扩展
这个问题是一个非常常见的问题
您应该能够在这方面使用动态规划。我强烈推荐它。假设我们正在为nodei
找到解决方案。假设我们已经有了节点i.left
和i.right
的解决方案,还假设我们有了它们的子节点(i
的孙子节点)的解决方案。对于i
的max解决方案,我们现在有两个选项:
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或使用备忘录。两者都应该有效。最好的部分是,现在您的解决方案是O(n)
谢谢。对于DP,您的意思是说,在您的响应的最后一行中,时间复杂度是O(n)还是O(n!)。我要去O(n)。@PepperBoy,是的O(n)
。我只是热情地说:)谢谢。对于DP,您的意思是说,在您的响应的最后一行中,时间复杂度是O(n)还是O(n!)。我要去O(n)。@PepperBoy,是的O(n)
。我只是热情地说:)