【问题标题】:Recursive to iterative when using recursive-result for other calculatons使用 recursive-result 进行其他计算时递归到迭代
【发布时间】:2018-09-19 01:08:54
【问题描述】:

理论上应该可以将每个递归方法写成一个迭代方法。

我知道递归函数是尾递归的很容易。例如,可以像这样递归地计算阶乘:

// Recursive:
long fact(long n){
  return fact(n, 1);
}
long fact(long n, long r){
  return n==1 ?
    r
   :
    fact(n-1, r*n);
}

Try it online.

或者像这样的迭代:

// Iterative:
int fact(int n){
  int r = 1;
  for(; n>1; n--)
    r *= n;
  return r;
}

Try it online.

这很简单,因为我们不会将递归方法的结果用于其他事情,而且我们只有一个递归调用,我们将 n 减少 1 次迭代。


我也知道您应该为大多数递归到迭代转换保留一个堆栈。例如,可以像这样递归地进行快速排序:

// Recursive:
void quicksort(int[] array, int left, int right){
  if(left >= right) return;
  int index = partition(array, left, right);
  quicksort(array, left, index-1);
  quicksort(array, index+1, right);
}

Try it online.

或者像这样的迭代:

// Iterative:
void quicksort(int[] array, int left, int right){
  int[] stack = new int[1024]; // Example size, alternative an actual java.util.Stack could be used
  int i=0;
  stack[i++] = left;
  stack[i++] = right;

  while(i>0){
    right = stack[--i];
    left = stack[--i];
    if(left >= right) continue;
    int index = partition(array, left, right);
    stack[i++] = left;
    stack[i++] = index-1;
    stack[i++] = index+1;
    stack[i++] = right;
  }
}

Try it online.


但我现在也想将以下递归方法转换为它的迭代形式:

// Recursive:
int f(int n){
  return n<1 ?
    0
   :
    n%2+1 + 3*f(n/2);
}

Try it online.

在这种情况下,它使用递归结果,并将该结果乘以 3。我也不完全确定如何进行迭代。我尝试过这样的事情:

// Iterative:
int f(int n){
  int[] stack = new int[1024]; // Example size, alternative an actual java.util.Stack could be used
  int i=0;
  stack[i++] = n;
  while(i > 0){
    n = stack[--i];
    if(n < 1)
      stack[i++] = 0;
    stack[i++] = n%2+1 + 3*stack[--i];
  }
  return stack[0];
}

这显然是行不通的,因为在i=1进入while之前,它在n = stack[--i]处变为0,然后在stack[i++] = n%2+1 + ...处再次变为1,然后在3*stack[--i]处再次变为0,所以它在第一次迭代后停止,并简单地返回stack[0]。当我将递归调用的结果与其他计算(在这种情况下乘以 3)一起使用时,我应该如何将上述递归方法转换为迭代方法?


至于原因:我想将上面的这种递归方法移植到没有任何功能的基于堆栈的语言中,因此我需要迭代方法(带堆栈)。

【问题讨论】:

    标签: java loops recursion stack iteration


    【解决方案1】:

    好的,我已经弄清楚了。我首先需要用 n%2+1 部分填充整个堆栈,每次迭代除以 2。并且只要n &lt; 1,我需要一个内部循环来计算结果。

    这是我最终得到的结果:

    // Recursive:
    int f(int n){ // i.e. n=2
      int[] stack = new int[1024]; // Example size, alternative an actual java.util.Stack could be used 
      int i=0;
      while(i >= 0){
        stack[i++] = n%2+1;
        n/=2;
        if(n < 1){
          while(i > 0){
            n = 3*n + stack[--i];
          }
          return n;
        }
      }
      return -1; // It should never come here, but the method need a return-statement
    }
    

    Try it online.

    【讨论】:

      【解决方案2】:

      我最终得到了类似的东西(之后才看到你的自我回答)

      int iterf(int n){
      
          //can also be implemented with an array. easier with list. 
          List<Integer> sum = new ArrayList<>();
      
          while (true) {
              if( n < 1 ) { //equivalent to if(n<1) return 0;
                  sum.add(0);
                  break;
              }
              //for each n, fill list with the fixed argument part: (n%2)+1
              sum.add((n%2)+1); 
              n=n/2;
          }
      
          //add to each list element 3 time the next element 
          //equivalent to 3*f(n/2);
          for(int i = sum.size()-2; i >=0; i--) {
              sum.set(i, sum.get(i) + (3*(sum.get(i+1))));
          }
      
          return sum.get(0);
      }
      

      【讨论】:

        猜你喜欢
        • 2015-05-18
        • 2016-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-15
        • 2023-03-09
        • 2013-03-30
        相关资源
        最近更新 更多