`
justshare
  • 浏览: 106016 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
社区版块
存档分类
最新评论

递归计算向非递归计算转换模板

阅读更多
递归计算向非递归计算转换模板
http://www.iteye.com/post/567240
http://www.iteye.com/topic/201241

这一篇实现篇有些误入歧途了。为了通用化而复杂化。
这个问题本身是可以线性化的,不必要树形化。

楼主的代码里面,vlaues (hash map) 保存了所有的中间计算结果,这是没有必要的。这会带来空间的浪费。
楼主的代码本质上是一种查表法(参数值列列表 -> 返回值)。
我们可以简单的用 Method Cache (方法缓存)的方式来实现。
只要用AOP,给这个函数加上Cache缓存(key是 函数名 + 参数列表),就可以轻松实现需要的效果。

第一篇思路篇里面的图很形象。
相当于程序员自己维护一个数组形式的运行栈结构。
在一些支持Continuation的非栈语言中,运行栈其实是树形的运行堆,中间结果都是保留起来的,保留中间结果的这些工作都不需要自己做。
楼主相当于做了一些Continuation的树形运行堆的工作。在栈语言上模拟这种效果,有些事倍功半的感觉。

------------------------------

这类问题其实就是保存前几步中间计算结果的问题。

对于这个问题本身来说
f(x) = f(x-1) + f(x-3)
f(x) = 10 (x < 3)

其实是很简单的,只需要用一个长度为3的数组保存中间结果就可以了。
Java代码 复制代码

    fibonacci(int x){ 
      if(x < 3) 
        return 10; 
     
     
      int[] middleResults = new int[3]{10,10,10}; 
      int result = 0; 
     
      for(int i = 10; i <= x; i++){ 
       result = middleResults[0] + middleResults[2]; 
       move(middleResults); 
       middleResults[0] = result; 
     } 
    
     return result; 
   } 
    
   void move(int[] array){ 
     int k = array.length; 
     int limit = k – 1; 
     for(int i = 0; i < limit; i++){ 
       array[i+1] = array[i]; 
     } 
   } 

fibonacci(int x){
  if(x < 3)
    return 10;


  int[] middleResults = new int[3]{10,10,10};
  int result = 0;

  for(int i = 10; i <= x; i++){
    result = middleResults[0] + middleResults[2];
    move(middleResults);
    middleResults[0] = result;
  }

  return result;
}

void move(int[] array){
  int k = array.length;
  int limit = k – 1;
  for(int i = 0; i < limit; i++){
    array[i+1] = array[i];
  }
}




move 方法主要用来移动中间结果数组里面的中间结果。
其实完全可以用一个 queue 队列来保存中间结果。直接把用过的 queue head 丢弃,把后面的结果加在队尾。正如楼主的代码里面用的queue结构。
只是为了更加形象地表达数组(运行栈)的结构,因此这里用了定长数组。


代码没有调试过,只是一个大概意思。
这段代码是循环形式,也可以写成递归形式,中间结果数组作为参数进行传递。

-------------------------

这个问题本身是Fibonacci问题的变种

Fibonacci问题描述:
1头母牛,出生后第3年,就开始每年生1头母牛,按此规律,第n年时有多少头母牛。
f(1)=1
f(2)=1
f(n)=f(n-1)+f(n-2)

Fibonacci数列:1,1,2,3,5,8,13,,21,34........

Fibonacci问题变种A描述:
1头母牛,出生后第4年,就开始每年生1头母牛,按此规律,第n年时有多少头母牛。
f(1)=1
f(2)=1
f(3)=1
f(n)=f(n-1)+f(n-3)

Fibonacci数列:1, 1, 1, 2, 3, 4, 6, 9,13,19,28........

Fibonacci问题通用描述:
1头母牛,出生后第x年,就开始每年生1头母牛,按此规律,第n年时有多少头母牛。
令k = x - 1
f(1)=1

f(k)=1
f(n)=f(n-1)+f(n-k)

-------------------------------------

递归函数:f(x) = ( f(x-1) + f(x-3) + x) / f(x-2), f(x) = 10 (x < 3)
同样可以类似解决。
Java代码 复制代码

   
  1. f(double x){ 
  2.       if(x < 3) 
  3.         return 10; 
  4.      
  5.      
  6.       double[] middleResults = new double[3]{10,10,10}; 
  7.       double result = 1; 
  8.      
  9.       for(int i = 10; i <= x; i++){ 
  10.        result = (middleResults[0] + middleResults[2] + i) / middleResult[1]; 
  11.        move(middleResults); 
  12.        middleResults[0] = result; 
  13.      } 
  14.     
  15.      return result; 
  16.    } 
  17.     
  18.    void move(int[] array){ 
  19.      int k = array.length; 
  20.      int limit = k – 1; 
  21.      for(int i = 0; i < limit; i++){ 
  22.        array[i+1] = array[i]; 
  23.      } 
  24.    } 
分享到:
评论

相关推荐

    递归向非递归的转换问题

    递归向非递归的转换问题一直是一个容易忽视的问题,所以重新整理了一下供大家批评指教

    递归算法到非递归算法的转换.ppt

    例如,计算阶乘的递归算法会根据n的值调用自身计算n-1的阶乘,直到n等于0,这时递归停止,返回1。这就是递归的终止条件。 递归通常在以下三种情况下被使用: 1. 定义是递归的:比如,Fibonacci数列的定义就涉及到...

    递归计算Ackermann函数的实现.zip

    递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算...

    使用递归计算阶乘

    java中使用递归方法计算阶乘的代码示例

    c语言 二叉树应用:创建、递归非递归遍历、计算结点、分支、交换子树

    递归计算单分支结点: 递归计算双分支结点: 递归计算叶子数: 二叉数的深度: 交换二叉树的左右子树: 二叉树已左右交换。 递归先序遍历二叉树: 递归中序遍历二叉树: 递归后序遍历二叉树:

    递归能更好的适用于反向计算(递归计算十进制转二进制)

    递归能更好的适用于反向计算(递归计算十进制转二进制)

    递归实现的表达式计算

    在这个主题“递归实现的表达式计算”中,我们将深入探讨如何使用递归方法解析和计算数学表达式。递归的核心思想是解决问题的子问题与原问题具有相同的形式,因此可以通过调用自身来解决。 首先,我们要理解表达式...

    递归计算文件夹大小源码

    搜索文件夹子目录、递归计算文件夹大小vc源码

    计算递归函数调用次数

    而迭代则是将递归转换为循环,通常可以更有效地控制资源使用。 总的来说,理解和计算递归函数调用次数是编程中的重要技能,它涉及到算法分析、性能优化和问题解决策略等多个方面。通过熟练掌握递归,程序员能更好地...

    递归子程序计算ackermann函数ACK(m,n)

    在汇编语言中实现Ackermann函数,我们需要创建一个递归子程序来计算这个函数。首先,我们需要定义数据段来存储输入的m和n以及计算过程中的临时结果。在本例中,我们有以下数据段定义: ```assembly data segment mm...

    python递归计算N!的方法

    本文实例讲述了python递归计算N!的方法。分享给大家供大家参考。具体实现方法如下: def factorial(n): if n == 0: return 1 else: return n * factorial(n - 1) 希望本文所述对大家的Python程序设计有所帮助...

    可计算原始递归等计算理论问题

    计算理论是计算机科学的基础之一,其中可计算性和递归理论是核心概念。可计算性探讨的是哪些数学函数可以通过有效的算法来求解。原始递归函数是最早被定义的一类可计算函数,它们通过简单的构建块和有限步骤的组合来...

    串行FFT递归算法(蝶式递归计算原理)求傅里叶变换.pdf

    **串行 FFT 递归算法(蝶形递归计算原理)求傅里叶变换** 傅里叶变换是一种在数学和工程领域广泛使用的分析工具,它能够将信号从时域转换到频域,揭示信号的频率成分。快速傅里叶变换(FFT)是离散傅里叶变换(DFT...

    串行FFT递归算法(蝶式递归计算原理)求傅里叶变换.docx

    **串行FFT递归算法(蝶式递归计算原理)求傅里叶变换** 傅里叶变换是一种在信号处理和图像处理领域广泛应用的数学工具,它将时域或空域的信号转换为频域表示,有助于分析信号的频率成分。快速傅里叶变换(FFT)是...

    递归和非递归方式计算Ackerman函数

    非递归(迭代)实现通常涉及将递归转换为循环,并使用数据结构(如堆栈)来存储中间结果。在计算 Ackerman 函数时,我们可以创建一个堆栈,模拟递归调用的过程。首先,我们将初始参数m和n压入堆栈。然后,进入一个...

    可并行递归算法的递归多线程实现

    本文旨在探讨如何在递归算法中运用多线程技术,以实现高效的并行计算。 #### Java多线程框架与递归算法结合 Java作为一门广泛使用的高级编程语言,其内置的多线程机制为开发者提供了丰富的工具,以便在多核架构上...

    简单的递归函数,计算1-100的和

    递归计算(1-100)的和 !

    数据结构:栈的应用-递归函数转非递归函数

    在这个主题中,我们将深入探讨如何利用栈来转换递归函数,将其优化为非递归形式,以提高计算效率。 首先,让我们了解递归函数。递归是一种解决问题的方法,函数通过调用自身来解决更小规模的问题。例如,阶乘是一个...

    C#递归计算求阶乘和求年龄实例源码

    C#递归计算求阶乘和求年龄实例源码 1、n!=n*(n-1)*(n-2)*......*3*2*1 n!=n*(n-1)! 2、 趣味问题——年龄。有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个...

Global site tag (gtag.js) - Google Analytics