英文:
Ternary operator confusion in Java
问题
以下是您提供的代码的中文翻译:
我正在解决LeetCode 437路径总和 III问题https://leetcode.com/problems/path-sum-iii/
我的原始代码如下,已通过所有测试:
public int pathSum(TreeNode root, int sum) {
if (root == null) {
return 0;
}
return pathSumStartWithRoot(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum);
}
private int pathSumStartWithRoot(TreeNode root, int sum) {
if (root == null) return 0;
int res = root.val == sum ? 1 : 0;
return res
+ pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val);
}
关于私有方法中的 int res = root.val == sum ? 1 : 0;
,我理解您的困惑。当我试图简化代码时,我删除了这行并将返回值更改为:
return root.val == sum ? 1 : 0
+ pathSumStartWithRoot(root.left, sum - root.val) + pathSumStartWithRoot(root.right, sum - root.val);
然而,这个更改导致了一些测试失败。例如,
TreeNode: [1,-2,-3,1,3,-2,null,-1], Sum: -1
正确的输出应该是4,但通过这个更改后,输出变成了3。
更令人惊讶的是,当我改变加法的顺序,例如将三元运算符放在最后:
return pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val)
+ root.val == sum ? 1 : 0;
输出变成了2。
我真的不知道发生了什么。在我看来,加法的顺序不应该影响最终结果。我对三元运算符不是很熟悉,我猜测这个问题可能是由于不正确的使用引起的?我在互联网上搜索了很多,但仍然找不到原因。感谢任何人的解释。
英文:
I am doing LeetCode 437 Path Sum III https://leetcode.com/problems/path-sum-iii/
and my original code is as follows which passed all tests:
public int pathSum(TreeNode root, int sum) {
if (root == null) {
return 0;
}
return pathSumStartWithRoot(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum);
}
private int pathSumStartWithRoot(TreeNode root, int sum) {
if (root == null) return 0;
int res = root.val == sum ? 1 : 0;
return res
+ pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val);
}
My confusion is from int res = root.val == sum ? 1 : 0;
in the private method. When I tried to shorten my code, I deleted this line and changed the return value to
return root.val == sum ? 1 : 0
+ pathSumStartWithRoot(root.left, sum - root.val) + pathSumStartWithRoot(root.right, sum - root.val);
However, this change caused some tests to fail. For example,
> TreeNode: [1,-2,-3,1,3,-2,null,-1], Sum: -1
The correct output should be 4 but with this change the output is 3.
More surprisingly, when I change the order of addition, say put the ternary to the last:
return pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val)
+ root.val == sum ? 1 : 0;
the output is changed to 2.
I really had no idea what happened here. In my opinion, the order of addition should not matter the final result. I'm not very familiar with the ternary operator and I guess this issue might be due to the incorrect use? I searched a lot on the Internet but still couldn't find out the reason. Thanks for anyone's explanation.
答案1
得分: 5
> 在我看来
不幸的是,你的看法对编译器不相关。
int a = condition ? 1 : 0;
int b = a + c;
等同于:
int b = (condition ? 1 : 0) + c;
而不等同于:
int b = condition ? 1 : 0 + c;
因为这与以下表达式相同:
int b = condition ? 1 : (0 + c);
这是因为 +
的优先级高于 ?:
。(查看运算符的优先级表)。
所以,如果你想内联条件表达式,需要使用括号来表示预期的优先级。
return (root.val == sum ? 1 : 0)
// ^-----------------------^ 额外的括号。
+ pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val);
英文:
> In my opinion
Unfortunately, your opinion isn't relevant to the compiler.
int a = condition ? 1 : 0;
int b = a + c;
is equivalent to:
int b = (condition ? 1 : 0) + c;
It's not equivalent to:
int b = condition ? 1 : 0 + c;
because that's the same as:
int b = condition ? 1 : (0 + c);
owing to +
having higher precedence than ?:
. (See table of precedence of the operators).
So if you want to inline the conditional expression, you need to use parentheses to indicate the intended precedence.
return (root.val == sum ? 1 : 0)
// ^-----------------------^ Extra parens.
+ pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val);
答案2
得分: 0
你甚至在面试时也不应该这样做。那个“缩短”代码与算法设计无关,与效率(时间或内存)无关,我猜。
另一个观点是,[tag:java] 和 [tag:c++] 并不适用于编写一行代码。
只需遵循惯例:
public class Solution {
public final int pathSum(TreeNode root, int sum) {
HashMap<Integer, Integer> prefixSum = new HashMap<>();
prefixSum.put(0, 1);
return helper(root, 0, sum, prefixSum);
}
private static final int helper(TreeNode node, int currSum, int target, HashMap<Integer, Integer> prefixSum) {
if (node == null)
return 0;
currSum += node.val;
int res = prefixSum.getOrDefault(currSum - target, 0);
prefixSum.put(currSum, 1 + prefixSum.getOrDefault(currSum, 0));
res += helper(node.left, currSum, target, prefixSum) + helper(node.right, currSum, target, prefixSum);
prefixSum.put(currSum, prefixSum.get(currSum) - 1);
return res;
}
}
参考资料
英文:
You should not even do that for interviews. That "shortening" code is irrelevant to algorithm design, and has nothing to do with efficiency (time or memory), I guess.
Another point is that [tag:java] and [tag:c++] are not designed for writing one liners.
Just follow the conventions:
public class Solution {
public final int pathSum(TreeNode root, int sum) {
HashMap<Integer, Integer> prefixSum = new HashMap<>();
prefixSum.put(0, 1);
return helper(root, 0, sum, prefixSum);
}
private static final int helper(TreeNode node, int currSum, int target, HashMap<Integer, Integer> prefixSum) {
if (node == null)
return 0;
currSum += node.val;
int res = prefixSum.getOrDefault(currSum - target, 0);
prefixSum.put(currSum, 1 + prefixSum.getOrDefault(currSum, 0));
res += helper(node.left, currSum, target, prefixSum) + helper(node.right, currSum, target, prefixSum);
prefixSum.put(currSum, prefixSum.get(currSum) - 1);
return res;
}
}
References
答案3
得分: 0
+
运算符的优先级高于三元运算符 ?:
,因此你的代码部分会首先执行加法操作,然后才是三元运算部分,如下所示:
return ((pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val)
+ root.val) == sum) ? 1 : 0;
因此,你可以在三元运算部分使用括号来明确优先级:
return pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val)
+ (root.val == sum ? 1 : 0);
英文:
+
operator precedence is higher than ternary operator ?:
so you code
pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val)+ root.val
this addition part will works first then ternary part like
return ((pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val)
+ root.val) == sum) ? 1 : 0;
So you can use bracket for tenary portion
return pathSumStartWithRoot(root.left, sum - root.val)
+ pathSumStartWithRoot(root.right, sum - root.val)
+ (root.val == sum ? 1 : 0);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论