一个神秘的stackoverflow错误?

时间:2013-05-31 05:51:10

标签: java recursion stack-overflow

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

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

2 个答案:

答案 0 :(得分:4)

这是一个臭名昭着的微妙错误。看看这个递归调用:

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

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

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

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

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

希望这有帮助!

答案 1 :(得分:1)

++start(称为预增量)评估为start+1start++(称为后增量,如增量在评估后完成)评估为start。他们都将变量中的值设置为start+1作为评估的副作用。因此,当您执行start++时,您将start传递给方法的下一次调用,该方法将start传递给方法的下一次调用...您永远不会到达基本情况而您无限地递归。