-1

我只是在热身,我偶然发现了这个:

http://codingbat.com/prob/p145416

这三种方法的区别在于我如何在递归调用中添加 start 参数。

我最初使用列出的第二个函数解决了它,但是它给了我臭名昭著的 stackoverflow 错误。第一个没有给我stackoverflow错误。这个站点有什么问题吗,还是有区别 1 和 2,即 Java 语言的一个微妙部分?

public boolean groupSum(int start, int[] nums, int target) {
    if (start >= nums.length) 
        return (target == 0);

    return groupSum(start+1, nums, target - nums[start]) || groupSum(start+1,      
       nums, target);
}

------------ 这些会导致堆栈溢出错误 --------------

public boolean groupSum(int start, int[] nums, int target) {
    if (start >= nums.length) 
        return (target == 0);

    return groupSum(start++, nums, target - nums[start]) || groupSum(start++,      
       nums, target);
}

public boolean groupSum(int start, int[] nums, int target) {
    if (start >= nums.length) 
        return (target == 0);

    return groupSum(++start, nums, target - nums[start]) || groupSum(++start,      
       nums, target);
}
4

2 回答 2

4

这是一个众所周知的微妙错误。看看这个递归调用:

groupSum(start++, nums, target - nums[start])

请注意,您是start++作为第一个参数传递的。这使用后缀++运算符,它执行以下操作:

  • 增量start,然后
  • 返回start曾经拥有的值。

换句话说,这会将 的本地副本更新startstart + 1,然后将 的旧值传递给start递归调用。这意味着start从调用到调用永远不会改变,所以基本情况永远不会触发,因此堆栈溢出。System.out.println您可以通过在函数顶部放置一条语句来确认这一点。

这里可能还有其他问题,但我怀疑这是你的罪魁祸首。

希望这可以帮助!

于 2013-05-31T05:55:26.090 回答
1

++start(称为预增量)计算为start+1. start++(称为后增量,因为增量是在评估之后完成的)评估为start。他们都将变量中的值设置start+1为评估的副作用。所以,当你start++传递start给方法的下一个调用时,它传递start给方法的下一个调用......你永远不会达到基本情况,你会无限递归。

于 2013-05-31T05:55:06.173 回答