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
上面的树只是sum3
的一个根到叶路径。但是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) ) );
}
}