Java 二叉树hasPathSum()实现

Java 二叉树hasPathSum()实现,java,algorithm,data-structures,tree,binary-tree,Java,Algorithm,Data Structures,Tree,Binary Tree,嗨 我正在尝试实现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. Strat

嗨 我正在尝试实现
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)); 
  } 
这是一个正确的实现吗

我在想这是不是应该

  • 如果(node.left==null和&node.right==null)
如果我错了,请澄清我的困惑

考虑这种情况:

          5
         / \
        2   1
       /    
      3

-谢谢

您真的应该编写代码并尝试一下,这样您可以学到很多东西。(编辑:我当然是…)

我相信原始代码对于hasPathSum(tree,7)失败,因为节点2不是叶

编辑:

原始代码由于明显的错误而被撤回-至少对除我之外的所有人来说是明显的:-)

编辑:


我的新解决方案如下。请注意,包含的优化(
if(sum)由于Bert没有修正他的答案,我将发布正确的答案

是的,你是对的,原始代码被破坏了,尽管这里的大多数人都这么说

      5
     / \
    2   1
   /    
  3
召唤

hasPathSum(root, 7);
将返回
true
,尽管没有添加到7的根到叶路径。这是因为当到达节点
2
时,它递归检查正确的子级(总和为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;
  } 
}
如果需要,可以将else块滚动成一个长语句(许多and和OR),但我发现这个语句更干净。

嗨,伙计们 谢谢你的回答,这个讨论看起来很有趣, 昨晚我再次尝试实现此功能,我认为我的解决方案适用于所有情况

实际上,我是以更简单的方式实现的,这样每个人都可以理解


有四个案例需要检查

  • 如果两个孩子都为空(我们的目标案例)
  • 如果仅存在右子级(表示左子级为空)
  • 如果只存在左子级(表示右子级为空)
  • 如果两个子节点都存在(表示节点具有左和右子节点)
  • 一种特殊情况:如果您将输入树直接作为null传递,则需要处理它(如果block req,则需要再处理一个)

    public静态布尔hasPathSum(tnoderoot,int-sum)
    {
    if(root==null)//仅当直接传递null时才调用它
    返回false;
    int subsum=和根数据;
    
    //如果(subsumOP)的功能在以下简单情况下明显失效:

       1
        \
         2
    
    上面的树只是sum
    3
    的一个根到叶路径。但是OP的函数将为
    hasPathSum(根,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版本:

    这里有一种替代方法,可以计算每个路径的总和,并将其与目标值相匹配。嗯,这似乎比使用子集合的逻辑更直观

    此外,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;
    
    }
    
    public静态布尔hasPathSum(节点根、int-sum、int-val、ArrayList nums){
    if(root==null){
    返回值(总和=0);
    }
    val=val+root.data;
    if(root.right==null&&root.left==null){
    添加(val)个数;
    返回值(val==总和);
    }
    布尔左=hasPathSum(root.left,sum,val,nums);
    布尔右=hasPathSum(root.right、sum、val、nums);
    向左| |向右返回;
    }
    
    试试这个

       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) ) );  
            }
       }
    
    bool hasPathSum(结构节点*节点,整数和){
    如果(node==NULL){
    返回false;
    }
    如果((和-(节点->数据)==0)&&&&(节点->左==NULL)&&(节点->右==NULL)){
    返回true;
    }
    如果(和-(节点->数据)<0{
    返回false;
    }否则{
    return(hasPathSum(节点->左侧,sum-(节点->数据))| | hasPathSum(节点->右侧,sum-(节点->数据)));
    }
    }
    
    为什么不进行测试并找出答案?是的,每个人都忽略了一个事实,即原始解决方案将具有一个子节点的节点视为“叶”。但您的更正是完全错误的。您的第一次更正要求到叶子的所有路径都有正确的和,这不是必需的。您的第二个备选方案确实是一团糟,但这个想法应该是可行的。@mokus,错了,当其中一个子项为空时,它将终止。这意味着在OP的示例中
    hasPathSum(root,7)
    将在不应该的情况下返回true。不幸的是,在答案确定之前,我无法修正投票。第一个修正仍然是完全错误的,第二个修正需要更好的null处理,当其中一个子项为null而不是另一个时。@mokus:不,不是。我在谈论OP发布的原始解决方案。Run I“T”和“看”。或者考虑一个具有根<代码> 5 < /C>的树和一个左节点<代码> 1 < /C> >当你调用<代码> HasPoSUM(根,5)< /代码>时,会发生什么?@伯特:是的,虽然显然没有其他人是:-),听起来我们同意(1)“Lead只指没有子节点”,(2)“HasPothSM(根,7))。是一个有效的测试失败-一个正确的解决方案应该返回假,但原始代码将返回真实的“谢谢马克-我正在做的事情,但我试图做太多的事情一次。唯一要考虑的是,这个解决方案不处理一个空树(节点= = null))是的,如果读者认为应该的话,我会把它作为练习留给他们。谢谢马克给出的清晰的解决方案,我在这里用过-。
       1
        \
         2
    
    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;
            }
    }
    
    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;
    
    }
    
       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) ) );  
            }
       }