我试图理解代码中的逻辑来解决Path Sum。这是Gayle Laakmann McDowell的书中解决的问题,尽管我的代码看起来有点不同。
问题:给定一个二进制树,每个节点包含一个整数值,计算总和为目标值的所有(向下)路径。
代码:
private Map<Integer, Integer> map = new HashMap<>();
private int count = 0;
private int pathSum(BinaryTreeNode root, int tgtSum)
{
map.put(0, 1);
pathSum(root, 0, tgtSum);
return count;
}
private void pathSum(BinaryTreeNode root, int runningSum, int tgtSum)
{
if (root == null) return;
runningSum += root.data;
if (map.containsKey(runningSum - tgtSum))
{
count += map.get(runningSum - tgtSum);
}
if (map.containsKey(runningSum))
{
map.put(runningSum, map.get(runningSum) + 1);
}
else
{
map.put(runningSum, 1);
}
pathSum(root.left, runningSum, tgtSum);
pathSum(root.right, runningSum, tgtSum);
map.put(runningSum, map.get(runningSum) - 1);
}
我的问题:
我(有点)理解runningSum
作为键存储在地图中的逻辑,(runningSum - tgtSum)
的值必须作为地图中的一个键存在连续节点加起来为tgtSum
,因为该差异将是某个其他节点的runningSum。
我无法理解的是,为什么我们无法取代
count += map.get(runningSum - tgtSum)
与count++
?
我试过调试它,我可以看到,在某些情况下,如果同一个分支有多个连续节点加起来tgtSum
,使用count++
只计数一次,而使用存储的频率以上方式的地图给出了正确的输出。
虽然我花了一些时间调试后能够把它弄好,但我无法通过使用{{1}的映射将这部分更新变量count
的逻辑与问题的基本逻辑联系起来作为键和运行总和的频率作为值。
任何人都可以简化和解释吗?
答案 0 :(得分:1)
让我们在执行过程中的某处选择功能。跳过计数增加的第一部分。接下来的两条指令与记录已记录的相同runningSum
的数量有关:如果我们已经看到它,则递增;否则,为runningSum
键分配一个计数。
现在让我们回到指令递增计数。想象一下,当runningSum
为12并且地图中已记录tgtSum
键时,我们已达到20 - 12 = 8
20。这意味着runningSum
在前往当前位置的某个早期节点处为8。
...
...
A (runningSum 8) •
/
(runningSum 7) • (-1)
/
B (runningSum 8) • 1
/ \
(runningSum 11) • 3 ...
/ ...
C (runningSum 20) • 9
...
...
我们需要计算从A
到C
的路径以及从B
到C
的路径,因此我们添加到{{1}的总计数8(存储为映射中键8的值),表示从runningSum
为8的节点开始的所有段,并结束我们当前的位置(在这种情况下为2段)。
现在让我们说runningSum
再次到达runningSum
的正确孩子的某个地方B
。对于我们发现的两个新段总计为12,我们再次将计数增加2。在完成B
的两个子树之后,我们减少了为runningSum
8存储的值,因为我们已经计算了可以从那里开始的所有有效段。
最后一条指令“map.remove(runningSum);”对我来说似乎不对。它应该是“递减”,否则我们将无法正确计算从A
开始的段到节点B
之前的右子节点。您可以在此处找到此观察的确认信息:https://github.com/katlew/Cracking-Coding-Interview/blob/master/chapter_4/pathsWithSum.java
答案 1 :(得分:0)
您必须找到所有可能的路径,因此需要所需总和的频率。如果你计算++,答案只计算一条路径而不是所有可能的路径。
考虑以下示例:
2
3 4
1 4 3 1
现在考虑路径2-> 3-> 4和2-> 4-> 3它们两者总和为相同的值 但他们是两条不同的道路。如果您只将计数增加1,则会错过另一条路径,因此需要频率。