java在递归函数中保留信息

java在递归函数中保留信息,java,recursion,Java,Recursion,是否可以在不使用静态变量的情况下,通过java的helper函数保留信息 比如说, public void foo(){ int v = 0; fooHelper(2); } public void fooHelper(int depth){ v++; fooHelper(depth-1) } 也就是说,我希望在不丢失每个递归情况的信息的情况下更新变量v,而不必访问函数外部的变量。在范围(例如方法)中声明的变量只能在该范围内访问(例如,不在另一个方法中) 如果

是否可以在不使用静态变量的情况下,通过java的helper函数保留信息

比如说,

public void foo(){
    int v = 0;
    fooHelper(2);
}

public void fooHelper(int depth){
    v++;
    fooHelper(depth-1)
}

也就是说,我希望在不丢失每个递归情况的信息的情况下更新变量v,而不必访问函数外部的变量。

在范围(例如方法)中声明的变量只能在该范围内访问(例如,不在另一个方法中)

如果信息仅与方法相关,请将变量保留在方法中。如果信息与整个对象/类状态相关,则将其保留为类成员(静态/非静态)

例如:

public void someRecursiveMethod(int num) {
    while (num < 10) {
        num++;
        someRecursiveMethod(num);
        System.out.println("Current num = " + num);
    }
}
public void someRecursiveMethod(int num){
while(num<10){
num++;
someRecursiveMethod(num);
System.out.println(“当前数值=”+num);
}
}

您可以创建一个新类(糟糕),或者将变量作为参数传递并在fooHelper中返回。

为什么不将其作为实例变量(不一定是静态的)


您可以返回列表或类似的数据结构:

public List<Integer> fooHelper( int v, int depth ){
    if( depth == 0 ) return new ArrayList();

    v++;
    List<Integer> result = fooHelper( v, depth-1 );

    result.add( new Integer(v) );

    return result;
}
公共列表fooHelper(int v,int depth){
if(depth==0)返回新的ArrayList();
v++;
列表结果=fooHelper(v,深度-1);
结果。添加(新整数(v));
返回结果;
}

因为变量v是基元类型,所以在函数范围外对其所做的更改将不可见。您可以在类中声明变量v,比如State,并将State对象传递给递归函数以获得所需的效果

public void foo(){
    State state = new State();
    fooHelper(state, 2);
}

public void fooHelper(State state, int depth){
    state.v++;
    fooHelper(state, depth-1);
}

class State {
    int v;
}

希望有帮助。

您可以传递一个对象来存储每次递归调用的更新。类似下面的那个

public static void fooHelper(int depth, HashMap map){
      map.put(depth, "Call " + depth);
      if (depth > 0)
      {
        fooHelper(depth-1, map);
      }
      return;
    }

我想这就是所谓的回忆录。看起来像

class Fibonacci
{
     public Map < Integer , Integer > memorized = new HashMap < > ( ) ;

     public int fib ( int n )
     {
           if ( memoized . containsKey ( n ) )
           {
                 return memoized . get ( n ) ;
           }
           else
           {
                 int fib = // calculate recursively
                 memoized . put ( n , fib ) ;
                 return fib ;
           }
     }
}
类斐波那契
{
公共映射<整数,整数>记忆=新哈希映射<>();
公共int fib(int n)
{
如果(已记忆。容器(n))
{
返回备忘。获取(n);
}
其他的
{
int fib=//递归计算
记忆化。放置(n,fib);
返回fib;
}
}
}
您应该能够从该算法中获得良好的(非最佳)性能。递归斐波那契算法性能差的主要原因是b/c,它重复计算相同的值。使用递归+记忆,它不会多次计算任何值


感谢@Aristide指出了记忆和记忆之间的细微差别。

忘记所有告诉您在每次递归调用中声明属性或更新可变对象的答案。在真正的函数式递归样式中,您可以通过将信息作为参数和/或返回类型传递来“保留”信息

让我用一个简单的例子来说明,假设您想要递归地计算
int[]
中元素的总和。在这里,状态(递归调用之间需要保留的信息)是数组中的当前索引和到目前为止的总和。以下是如何做到这一点:

public int sum(int[] array) {
    return sum(array, 0, 0); 
}

private int sum(int[] array, int idx, int acc) {
    if (idx == array.length)
        return acc;
    return sum(array, idx+1, acc+array[idx]);
}
可以这样称呼:

int[] array = {1, 2, 3};
System.out.println(sum(array));
如您所见,不需要声明(静态或实例)属性,也不需要传递和修改可变对象(列表、映射)-我甚至不使用局部变量,因为解决问题所需的所有信息都作为方法参数提供


在您问题中的代码中,
v
变量应该执行我的回答中
acc
参数所做的操作,即:每次调用递归时修改累积值。最后,您只需要从helper函数返回累积值(该函数不能有
void
返回类型),这就是如何在
foo()

中获得值的方法,因此使用递归时静态变量是唯一的方法?@user1220022绝对不是,在递归期间使用属性存储状态是非常困难的(一般来说)没有必要。看看我的答案,我只使用参数来跟踪状态,没有使用变量。点击:它是。
int[] array = {1, 2, 3};
System.out.println(sum(array));