我在回忆的countunivaltrees问题上使用什么时间和空间复杂性
我尝试了这个挑战,但花了太长时间才能执行一些投入。问题如下
,您得到了一棵二进制树。在给定的二进制树中返回Unival子树的计数。在Unival树中,所有节点下方的所有节点都具有与根的数据相同的值。
我的第一次尝试失败,因为时间复杂性
def countUnivalTrees(tree):
if tree is None:
return 0
leftCount = countUnivalTrees(tree.left)
rightCount = countUnivalTrees(tree.right)
count = leftCount + rightCount
if isUnivalTree(tree, tree.value):
count += 1
return count
def isUnivalTree(tree, value):
if tree is None:
return True
if tree.value != value:
return False
if tree.left is None and tree.right is None:
return True
return isUnivalTree(tree.left, value) and isUnivalTree(tree.right, value)
给出了正确的答案,但可能需要太长的执行时间一些给定的输入。
我的第二种方法是记住我已经看到的东西。
def countUnivalTrees(root, memoized={}):
if root is None:
return 0
memoized[root] = False
leftCount = countUnivalTrees(root.left, memoized)
rightCount = countUnivalTrees(root.right, memoized)
count = leftCount + rightCount
if root.left is not None and root.right is not None:
if memoized[root.left] and memoized[root.right] and root.left.value == root.right.value and root.value == root.left.value:
memoized[root] = True
count += 1
elif root.left is not None:
if memoized[root.left] and root.value == root.left.value:
memoized[root] = True
count += 1
elif root.right is not None:
if memoized[root.right] and root.value == root.right.value:
memoized[root] = True
count += 1
else:
if isUnivalTree(root, root.value):
memoized[root] = True
count += 1
return count
isunivaltree
是第一次尝试的固定,因此我省略了它以不添加额外的代码。我能够通过所有测试。我的计划是具有o(n)
和o(n)
space的时间复杂性。我很难确切了解我的复杂性以及我的方法是否正确。通过正确,我的意思是准确地工作我应该是:
步骤1:访问树中的每个节点
:从叶到根检查电流根是单个单位。如果将root保存在记忆
中,然后将其映射到true
。
步骤3:如果当前的根节点具有左和右子节点,并且该节点在中记忆
映射到true
这意味着它是一个Unival树,而不是检查右和左子女值是相同和根值相同的,并且是一个单词树,将当前的根并映射到true。 (还要考虑只有一个剩下一个孩子或只有一个右孩子的根,并且执行这些检查o(1)操作),
所以我想象一棵大树的左右跨度,但所有相同的值。确实,我们正在查看所有节点,一旦O(n),n是节点的数量,然后当我们弹出堆栈记忆时,将当前的节点记忆并映射到True,如果isunivaltree
and>很快。
由于某种原因,我觉得我可能会缺少一个情况,我应该检查是否回忆[root.left] = false
,并且如果它不计数。不确定,除了fibonacci
编码问题之外,我从未回忆过,所以这对我来说是新的。
I was attempting this challenge but took too long to execute for some inputs. The question is as follows
You are given a binary tree. Return the count of unival sub-trees in the given binary tree. In unival trees, all the nodes, below the root node, have the same value as the data of the root.
My first attempt failed because of the time complexity
def countUnivalTrees(tree):
if tree is None:
return 0
leftCount = countUnivalTrees(tree.left)
rightCount = countUnivalTrees(tree.right)
count = leftCount + rightCount
if isUnivalTree(tree, tree.value):
count += 1
return count
def isUnivalTree(tree, value):
if tree is None:
return True
if tree.value != value:
return False
if tree.left is None and tree.right is None:
return True
return isUnivalTree(tree.left, value) and isUnivalTree(tree.right, value)
It gives the right answer but can take too long to execute for some given inputs.
My Second approach was to memoize what I've seen already.
def countUnivalTrees(root, memoized={}):
if root is None:
return 0
memoized[root] = False
leftCount = countUnivalTrees(root.left, memoized)
rightCount = countUnivalTrees(root.right, memoized)
count = leftCount + rightCount
if root.left is not None and root.right is not None:
if memoized[root.left] and memoized[root.right] and root.left.value == root.right.value and root.value == root.left.value:
memoized[root] = True
count += 1
elif root.left is not None:
if memoized[root.left] and root.value == root.left.value:
memoized[root] = True
count += 1
elif root.right is not None:
if memoized[root.right] and root.value == root.right.value:
memoized[root] = True
count += 1
else:
if isUnivalTree(root, root.value):
memoized[root] = True
count += 1
return count
The isUnivalTree
is indentical to the first attempt so I omitted it to not add the extra code. I was able to pass all tests. My plan was to have a time complexity of O(n)
and O(n)
space. I am having trouble understanding exactly what my complexity would be and if my approach is correct. By correct I mean working exactly how I believe it should be:
step 1: visit each node in the tree
step 2: from leaf to root check current root is unival or not. If it is save the root in memoized
and map it to true
.
step 3: if current root node has a left and right child node and that node in memoized
maps to true
meaning it is a unival tree than just check right and left child values to be the same and root value to be the same and is a unival tree memoize the current root and map to true. (also take into account for roots that have only one left child or only one right child and perform those checks as well O(1) operations)
So I'm imagining a big tree with many spanning left and right but with all the same values. Is it true that we are looking at all the nodes once O(n), where n is the number of nodes and then as we pop off the stack memoizing that current node and mapping to true if isUnivalTree
and so on.
For some reason I feel like I might be missing a case where I should check if memoized[root.left] = False
and if it is then not count it. Not sure really, I never memoized before besides for the fibonacci
coding problem so this is new to me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我们看不到回忆,因为我们看不到您的
isunivaltree
。但是,如果它很快,那么它肯定是o(n)
时间,因为您只访问每个节点最多2倍(一次计数树,一次查看是否标记为Unival),您将其记忆。但是没有必要记忆。只需一口气返回所需的所有上下文即可。如果那比您想使用的更混乱,那就有一个琐碎的包装器。
We can't see the memoization because we don't see your
isUnivalTree
. But if it is fast, then it is certainlyO(n)
time because you're only visiting each node a maximum of 2x (once to count trees, once to see if it was marked unival), on one of which you memoize it.But there is no need to memoize. Just return all of the context that you need in one go. And if that is messier than you want to use, then have a trivial wrapper.