繁体   English   中英

Java 中的三元运算符混淆

[英]Ternary operator confusion in Java

我正在做 LeetCode 437 Path Sum 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; 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);

但是,此更改导致某些测试失败。 例如,

树节点:[1,-2,-3,1,3,-2,null,-1],总和:-1

正确的 output 应为 4,但通过此更改,output 为 3。

更令人惊讶的是,当我改变加法的顺序时,说把三元放在最后:

        return pathSumStartWithRoot(root.left, sum - root.val) 
        + pathSumStartWithRoot(root.right, sum - root.val)
        + root.val == sum ? 1 : 0;

output 更改为 2。

我真的不知道这里发生了什么。 在我看来,添加的顺序与最终结果无关。 我对三元运算符不是很熟悉,我猜这个问题可能是由于使用不正确造成的? 我在互联网上搜索了很多,但仍然找不到原因。 感谢任何人的解释。

在我看来

不幸的是,您的意见与编译器无关。

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)
    // ^-----------------------^ Extra parens.
   + pathSumStartWithRoot(root.left, sum - root.val)
   + pathSumStartWithRoot(root.right, sum - root.val);

+运算符优先级高于三元运算符?:所以你编码

pathSumStartWithRoot(root.left, sum - root.val) 
 + pathSumStartWithRoot(root.right, sum - root.val)+ root.val

这个加法部分将首先起作用,然后是三元部分

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);

你甚至不应该在面试时这样做。 我猜,“缩短”代码与算法设计无关,与效率(时间或内存)无关。

还有一点是不是为写一个衬里而设计的。

只需遵循约定:

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;
    }
}

参考

  • 有关其他详细信息,您可以查看讨论板 有许多公认的解决方案,其中包含各种语言和解释、高效算法以及渐近时间/空间复杂度分析12

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM