我有一个递归函数,在第一次递归调用时添加值number
,在第二次递归调用时添加number-1
,依此类推,直到达到0.我已将此函数实现为:
public static int func(int number, int retval=0)
{
if (number<=0)
return retval;
return func( number-1, retval+number );
}
如果在使用大number
值调用时不创建堆栈溢出,我怎么能写这个?我需要一个单独的文件吗?
答案 0 :(得分:3)
在第一次递归调用中添加number
,在第二次添加number-1
,依此类推,直到最后添加0并停止递归。因此,这相当于只返回retval + number + (number-1) + ... + 1
,which is equal to retval + (number+1)*number/2
。
因此,您可以通过用以下函数替换函数来避免完全递归(以及堆栈溢出的可能性):
public static int func(int number, int retval=0)
{
if (number<=0) {
return retval;
} else {
return retval + (number+1)*number/2;
}
}
这种方法的另一个好处是它在O(1)
时间内运行,而你问题的递归方法和迭代对应方法都在O(number)
运行时运行。
答案 1 :(得分:0)
当你有一个类似你的递归函数时,它不会对递归调用的结果进行操作而只是将它返回给调用者,你可以用一个跳转到函数体的顶部并用适当的参数替换递归调用取代
对于你的功能:
public static int func(int number, int retval=0)
{
if (number<=0)
return retval;
return func( number-1, retval+number );
}
看起来像这样:
public static int func(int number, int retval=0)
{
top:
if (number<=0)
return retval;
//return func( number-1, retval+number );
number = number - 1;
retval = retval + number;
goto top;
}
要摆脱丑陋的goto
,你可以用while
循环代替(因为退出条件位于顶部)。
现在功能如下:
public static int func(int number, int retval=0)
{
while (! number<=0)
{
number = number - 1;
retval = retval + number;
}
return retval;
}
它不再是递归的,不会导致堆栈溢出。
答案 2 :(得分:-1)
如果必须使用递归,请在函数中添加一个整数,其中包含剩余的空格&#39;在堆栈中,类似于:
public static int func(int number, int retval=0, int numberOfCalls)
{
if(numberOfCalls >= maximumBeforeStackOverflow)
{
//throw exception you can catch (you can't cath stackoverflow if i'm correct)
//or break func
}
if (number<=0)
{
return retval;
}
return func( number-1, retval+number, numberOfCalls++ );
}