您好
我正在尝试实施hasPathSum()
对于给定数字的意思是在根到叶节点之间存在任何路径。
我从斯坦福大学的网站上获得了这段代码。我认为这是错误的
/**
Given a tree and a sum, returns true if there is a path from the root
down to a leaf, such that adding up all the values along the path
equals the given sum.
Strategy: subtract the node value from the sum when recurring down,
and check to see if the sum is 0 when you run out of tree.
*/
boolean hasPathSum(Node node, int sum) {
// return true if we run out of tree and sum==0
if (node == null){
return(sum == 0);
}
else {
// otherwise check both subtrees
int subSum = sum - node.data;
return(hasPathSum(node.left, subSum) || hasPathSum(node.right, subSum));
}
这是正确的实施吗?
我在想如果应
如果我错了请清除我的困惑
考虑这种情况:
5
/ \
2 1
/
3
-Thanks
答案 0 :(得分:4)
你真的应该只编码并尝试它 - 你会学到很多东西。 (编辑:我当然是...... )
我认为hasPathSum(tree, 7)
的原始代码失败,因为节点2不是叶子。
修改强>
原始代码由于明显的错误而被撤销 - 至少对我而言显而易见: - )
修改:
我的新解决方案如下。请注意,包含的优化(if (sum <= node.data)
)假定树由所有正数据值组成。如果树具有零或负数据值,则应将其删除或调整。 (感谢@Mark Peters)。
另请注意有关处理hasPathSum(null, 0)
的答案评论中的讨论。
static boolean hasPathSumBert(final Node node, final int sum) {
// return true if we run out of tree and sum==0
if (node == null) { // empty tree
// choose one:
return (sum == 0);
//return false;
} else if (node.left == null && node.right == null) { // leaf
return (sum == node.data);
} else if (sum <= node.data) { // sum used up
return false;
} else { // try children
return (node.left != null && hasPathSumBert(node.left, sum - node.data)) ||
(node.right != null && hasPathSumBert(node.right, sum - node.data));
}
}
完整代码:
public class TreeTest {
static class Node {
int data;
Node left;
Node right;
Node(final int data, final Node left, final Node right) {
this.data = data;
this.left = left;
this.right = right;
}
}
public static void main(final String[] args) {
final Node three = new Node(3, null, null);
final Node two = new Node(2, three, null);
final Node one = new Node(1, null, null);
final Node five = new Node(5, two, one);
final Node tree = five;
for (int i = 0; i <= 10; i++) {
System.out.println(i + "");
System.out.println("original = " + hasPathSum(tree, i));
System.out.println("bert = " + hasPathSumBert(tree, i));
System.out.println("mark = " + hasPathSumMark(tree, i));
System.out.println();
}
System.out.println("hasPathSumBert(null, 0): "+ hasPathSumBert(null, 0));
System.out.println("hasPathSumBert(null, 1): "+ hasPathSumBert(null, 1));
}
static boolean hasPathSum(final Node node, final int sum) {
// return true if we run out of tree and sum==0
if (node == null) {
return (sum == 0);
} else {
// otherwise check both subtrees
final int subSum = sum - node.data;
return (hasPathSum(node.left, subSum) || hasPathSum(node.right, subSum));
}
}
static boolean hasPathSumBert(final Node node, final int sum) {
// return true if we run out of tree and sum==0
if (node == null) { // empty tree
// choose one:
return (sum == 0);
//return false;
} else if (node.left == null && node.right == null) { // leaf
return (sum == node.data);
} else if (sum <= node.data) { // sum used up
return false;
} else { // try children
return (node.left != null && hasPathSumBert(node.left, sum - node.data)) ||
(node.right != null && hasPathSumBert(node.right, sum - node.data));
}
}
static boolean hasPathSumMark(final Node node, final int sum) {
final int subSum = sum - node.data;
if (node.left == null && node.right == null) {
return (subSum == 0);
} else {
// otherwise check both subtrees
if (node.left != null && hasPathSumMark(node.left, subSum))
return true;
if (node.right != null && hasPathSumMark(node.right, subSum))
return true;
return false;
}
}
}
样品运行:(注7)
0
original = false
bert = false
mark = false
1
original = false
bert = false
mark = false
2
original = false
bert = false
mark = false
3
original = false
bert = false
mark = false
4
original = false
bert = false
mark = false
5
original = false
bert = false
mark = false
6
original = true
bert = true
mark = true
7
original = true
bert = false
mark = false
8
original = false
bert = false
mark = false
9
original = false
bert = false
mark = false
10
original = true
bert = true
mark = true
hasPathSumBert(null, 0): true
hasPathSumBert(null, 1): false
答案 1 :(得分:4)
由于伯特没有修正他的答案,我会发布正确答案。
是的,尽管大多数人都在说,原始代码已被破坏,你说得对。在你的例子中
5
/ \
2 1
/
3
调用
hasPathSum(root, 7);
将返回true
,尽管没有添加到7的root-to-leaf路径。这是因为当到达节点2
时,它会以递归方式检查正确的子节点(使用sum 0) ),然后返回true,因为正确的孩子是null
。
修正案的灵感来自Bert的回答:
// `if` statement should check children and `return` statement deduct node.data from sum
boolean hasPathSum(Node node, int sum) {
int subSum = sum - node.data;
if(node.left==null && node.right==null) {
return(subSum == 0);
}
else {
// otherwise check both subtrees
if ( node.left != null && hasPathSum(node.left, subSum) ) {
return true;
if ( node.right != null && hasPathSum(node.right, subSum) ) {
return true;
}
return false;
}
}
如果你想要(很多ands和ors),你可以将else块转换成一个长语句,但我发现它更干净。
答案 2 :(得分:0)
实际上我以更简单的方式实施,以便每个人都可以理解
有四种情况需要检查
一个特殊情况:如果直接将输入树作为null传递,则需要处理(如果是块请求,则需要处理一个)
public static boolean hasPathSum(TNode root, int sum)
{
if(root==null) //it is called only if you pass directly null
return false;
int subsum = sum-root.data;
//if(subsum<0) return false; //uncomment this for reducing calls for negative numbers
if(root.left==null && root.right==null) //for leaf node
return (subsum==0);
if(root.left==null) //if only right child exist
return hasPathSum(root.right, subsum);
if(root.right==null)//if only left child exist
return hasPathSum(root.left, subsum);
return (hasPathSum(root.left, subsum) || hasPathSum(root.right,subsum));
}
请查看我的代码 这适用于所有二叉树案例吗?和 如果需要进行任何更改,请与我们联系。
-Thanks
答案 3 :(得分:0)
对于以下简单案例,OP的功能明显失败:
1
\
2
上面的树只是总和3
的叶子路径的一个根。但OP的函数将在hasPathSum(root,1)
这是因为仅当我们到达叶节点(空左子树和空右子树)或空树的特殊情况时,才应将变化的子和与零进行比较。
OP的功能是将NULL
子节点视为叶子。
以下功能(与Mark的+另外一项检查相同)修复了它:
boolean hasPathSum(Node node, int sum) {
// CASE 1: empty tree.
if (node == NULL) {
return sum == 0;
}
// CASE 2: Tree exits.
int subSum = sum - node.data;
// CASE 2A: Function is called on a leaf node.
if (node.left==null && node.right==null) {
return subSum == 0;
// CASE 2B: Function is called on a non-leaf node.
} else {
// CASE 2BA: Non-left node has desired path in left subtree.
if (node.left != null && hasPathSum(node.left, subSum) ){
return true;
}
// CASE 2BB: Non-left node has desired path in right subtree.
if ( node.right != null && hasPathSum(node.right, subSum) ) {
return true;
}
// CASE 2BC: Non-left node has no desired pat.
return false;
}
}
C版:Ideone Link
答案 4 :(得分:0)
这是另一种计算每条路径之和的方法,并将其与目标值相匹配。恕我直言,这似乎比使用子词的逻辑更直观。
此外,nums列表将存储所有根到叶路径的总和。我添加这个只是为了确保我的代码没有生成任何不需要的路径。
public static boolean hasPathSum(Node root, int sum, int val, ArrayList<Integer> nums) {
if(root == null) {
return (sum == 0);
}
val = val + root.data;
if(root.right == null && root.left == null) {
nums.add(val);
return (val == sum);
}
boolean left = hasPathSum(root.left, sum, val, nums);
boolean right = hasPathSum(root.right, sum, val, nums);
return left || right;
}
答案 5 :(得分:0)
试试这个
bool hasPathSum(struct node* node, int sum){
if(node == NULL){
return false;
}
if((sum - (node->data) == 0) && (node->left == NULL) && (node->right == NULL) ) {
return true;
}
if (sum - (node->data) < 0) {
return false;
} else {
return( hasPathSum (node->left,sum - ( node->data ) ) || hasPathSum (node->right, sum - (node->data) ) );
}
}