All Paths for a Sum with return issues(有返回问题的总和的所有路径)
问题描述
我有一个问题是要找到总和的所有路径.问题是:
<块引用>给定一棵二叉树和一个数字S",找到从根到叶的所有路径,使得每条路径的所有节点值之和等于S".
我的递归方法是:
输出是:
但是,正确的做法应该是:
有输出:
我在这里有一些问题:
为什么我们在递归语句中不需要
return
?我也对return
语句如何将输出减少到只有一个感兴趣?为什么我们不需要
result = find_sum_path(root, target, result, [])
?那么更新结果背后的逻辑是什么?不知道为什么时间复杂度是O(N^2)?
<块引用>
上述算法的时间复杂度为O(N^2),其中‘N’是树中节点的总数.这是因为我们遍历每个节点一次(这将花费 O(N)),并且对于每个叶节点,我们可能必须存储它的路径,这将花费 O(N).
提前感谢您的帮助.
首先,我想说你已经非常接近解决问题了,你已经完成了一项了不起的工作.递归是一种函数式遗产,因此将其与函数式风格一起使用会产生最佳结果.这意味着要避免诸如突变、变量重新分配和其他副作用之类的事情.这可以消除许多错误来源(和令人头疼的问题)!
为了美化你的程序,我们可以先修改 TreeNode
以在构造时同时接受 left
和 right
参数 -
现在我们可以定义两棵树,t1
和 t2
.请注意,我们不会重新分配 root
-
预期的输出是 -
最后我们实现了find_sum
.我们可以使用数学归纳法为我们的函数写一个简单的案例分析-
- 如果输入树
t
为空,则返回空结果 - (inductive)
t
是 not 空的.如果t.value
与目标q
匹配,则已找到解决方案;将t.value
添加到当前path
和 yield - (inductive)
t
不为空,并且t.value
与目标q
匹配 not.将t.value
添加到当前path
和新的子问题next_q
;解决t.left
和t.right
分支上的子问题 -
请注意我们如何不使用上面的 .append
之类的突变.为了计算 all 路径,我们可以将 all_find_sum
写成 find_sum
-
就是这样,你的程序已经完成了:D
如果不想使用单独的生成器find_sum
,我们可以就地扩展生成器-
请注意这两种变体之间的明显相似之处.任何编写良好的程序都可以轻松地在两种风格之间转换.
I have a question in finding the all paths for a sum. The question is:
Given a binary tree and a number ‘S’, find all paths from root-to-leaf such that the sum of all the node values of each path equals ‘S’.
My approach with recursion is:
and the output is:
However, the correct approach should be:
With output:
I have a some questions here:
Why don't we need a
return
in the recursion statement? I am also interested in how thereturn
statement reduced the output to only one?Why don't we need the
result = find_sum_path(root, target, result, [])
? Then what is the logic behind to update the results?I am not sure why the time complexity is O(N^2)?
The time complexity of the above algorithm is O(N^2), where ‘N’ is the total number of nodes in the tree. This is due to the fact that we traverse each node once (which will take O(N)), and for every leaf node we might have to store its path which will take O(N).
Thanks for your help in advance.
First off, I want to say you're very close to solving the problem and you've done a terrific job. Recursion is a functional heritage and so using it with functional style yields the best results. This means avoiding things like mutations, variable reassignments, and other side effects. This can eliminate many sources of bugs (and headaches)!
To spruce up your program, we can start by modifying TreeNode
to accept both left
and right
parameters at time of construction -
Now we can define two trees, t1
and t2
. Notice we don't reassign root
-
The expected output is -
Finally we implement find_sum
. We can use mathematical induction to write a simple case analysis for our function -
- if the input tree
t
is empty, return the empty result - (inductive)
t
is not empty. ift.value
matches the target,q
, a solution has been found; addt.value
to the currentpath
and yield - (inductive)
t
is not empty andt.value
does not match the targetq
. addt.value
to the currentpath
and new sub-problem,next_q
; solve the sub-problem ont.left
andt.right
branches -
Notice how we don't use mutations like .append
above. To compute all paths, we can write all_find_sum
as the expansion of find_sum
-
And that's it, your program is done :D
If you don't want to use a separate generator find_sum
, we can expand the generator in place -
Notice the distinct similarity between the two variations. Any well-written program can easily be converted between either style.
这篇关于有返回问题的总和的所有路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!