递归计算向非递归计算转换模板
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代码 复制代码
- f(double x){
- if(x < 3)
- return 10;
-
-
- double[] middleResults = new double[3]{10,10,10};
- double result = 1;
-
- for(int i = 10; i <= x; i++){
- result = (middleResults[0] + middleResults[2] + i) / middleResult[1];
- 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];
- }
- }
分享到:
相关推荐
递归向非递归的转换问题一直是一个容易忽视的问题,所以重新整理了一下供大家批评指教
例如,计算阶乘的递归算法会根据n的值调用自身计算n-1的阶乘,直到n等于0,这时递归停止,返回1。这就是递归的终止条件。 递归通常在以下三种情况下被使用: 1. 定义是递归的:比如,Fibonacci数列的定义就涉及到...
递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算Ackermann函数的实现.zip 递归计算...
java中使用递归方法计算阶乘的代码示例
递归计算单分支结点: 递归计算双分支结点: 递归计算叶子数: 二叉数的深度: 交换二叉树的左右子树: 二叉树已左右交换。 递归先序遍历二叉树: 递归中序遍历二叉树: 递归后序遍历二叉树:
递归能更好的适用于反向计算(递归计算十进制转二进制)
在这个主题“递归实现的表达式计算”中,我们将深入探讨如何使用递归方法解析和计算数学表达式。递归的核心思想是解决问题的子问题与原问题具有相同的形式,因此可以通过调用自身来解决。 首先,我们要理解表达式...
搜索文件夹子目录、递归计算文件夹大小vc源码
而迭代则是将递归转换为循环,通常可以更有效地控制资源使用。 总的来说,理解和计算递归函数调用次数是编程中的重要技能,它涉及到算法分析、性能优化和问题解决策略等多个方面。通过熟练掌握递归,程序员能更好地...
在汇编语言中实现Ackermann函数,我们需要创建一个递归子程序来计算这个函数。首先,我们需要定义数据段来存储输入的m和n以及计算过程中的临时结果。在本例中,我们有以下数据段定义: ```assembly data segment mm...
本文实例讲述了python递归计算N!的方法。分享给大家供大家参考。具体实现方法如下: def factorial(n): if n == 0: return 1 else: return n * factorial(n - 1) 希望本文所述对大家的Python程序设计有所帮助...
计算理论是计算机科学的基础之一,其中可计算性和递归理论是核心概念。可计算性探讨的是哪些数学函数可以通过有效的算法来求解。原始递归函数是最早被定义的一类可计算函数,它们通过简单的构建块和有限步骤的组合来...
**串行 FFT 递归算法(蝶形递归计算原理)求傅里叶变换** 傅里叶变换是一种在数学和工程领域广泛使用的分析工具,它能够将信号从时域转换到频域,揭示信号的频率成分。快速傅里叶变换(FFT)是离散傅里叶变换(DFT...
**串行FFT递归算法(蝶式递归计算原理)求傅里叶变换** 傅里叶变换是一种在信号处理和图像处理领域广泛应用的数学工具,它将时域或空域的信号转换为频域表示,有助于分析信号的频率成分。快速傅里叶变换(FFT)是...
非递归(迭代)实现通常涉及将递归转换为循环,并使用数据结构(如堆栈)来存储中间结果。在计算 Ackerman 函数时,我们可以创建一个堆栈,模拟递归调用的过程。首先,我们将初始参数m和n压入堆栈。然后,进入一个...
本文旨在探讨如何在递归算法中运用多线程技术,以实现高效的并行计算。 #### Java多线程框架与递归算法结合 Java作为一门广泛使用的高级编程语言,其内置的多线程机制为开发者提供了丰富的工具,以便在多核架构上...
递归计算(1-100)的和 !
在这个主题中,我们将深入探讨如何利用栈来转换递归函数,将其优化为非递归形式,以提高计算效率。 首先,让我们了解递归函数。递归是一种解决问题的方法,函数通过调用自身来解决更小规模的问题。例如,阶乘是一个...
C#递归计算求阶乘和求年龄实例源码 1、n!=n*(n-1)*(n-2)*......*3*2*1 n!=n*(n-1)! 2、 趣味问题——年龄。有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个...