您的位置:首页 > 编程语言 > Java开发

细谈递归,备忘录递归,动态规划,三种算法思想和运行原理

2018-01-03 22:08 267 查看
大家都知道,数值稍大的递归运行时间对于开发者来说就是场灾难,我们总是想方设法在优化递归,或者说不用递归,此文中从空间时间角度详细剖析以上三种算法的区别,以及运行原理,以斐波那契数为例, 编程语言java

此处为代码


package test1;

import java.util.HashMap;

public class test2 {
private static int count1=0;
private static int count2=0;
private static int count3=0;
public static void main(String[] args) {
System.out.println("***********************递归*********************");
long startTime1=System.nanoTime();
System.out.println(getNumber1(30));
long endTime1=System.nanoTime();
System.out.println("方法调用了"+count1+"次数");

System.out.println("时间为:"+(endTime1-startTime1)+"ns");
System.out.println("***********************备忘录递归*********************");
long startTime2=System.nanoTime();
System.out.println(getNumber2(30));
long endTime2=System.nanoTime();
System.out.println("方法调用了"+count2+"次数");

System.out.println("时间为:"+(endTime2-startTime2)+"ns");
System.out.println("***********************动态规划*********************");
long startTime3=System.nanoTime();
System.out.println(getNumber3(30));
long endTime3=System.nanoTime();
System.out.println("方法调用了"+count3+"次数");

System.out.println("时间为:"+(endTime3-startTime3)+"ns");
}
//递归
//   832040
//  方法调用了1664079次数
//  时间为:4839154ns

public static int getNumber1( int  m) {
count1++;
if(m==1||m==2)
{
return 1;
}
else
return getNumber1(m-1)+getNumber1(m-2);

}

// 备忘录算法,自上而下,记住之前算过的值。减少方法的访问次数从而减少运行时间
//方法调用了:57
//832040
//时间为:133048ns
private static HashMap<Integer, Integer> hm=new HashMap<>();
public static int getNumber2( int  m) {
count2++;
if(m==1||m==2)
{
return 1;
}
else if(hm.containsKey(m))
{
return hm.get(m);
}
else {
int  value =getNumber2(m-1)+getNumber2(m-2);
hm.put(m, value);
return value;
}
}
// 动态规划,自下向上的算法
//方法调用了:1
//时间为:3422ns
//832040

public static int getNumber3( int  m) {
count3++;
if(m==1||m==2)
{
return 1;
}
int  a=1;
int b=1;
int temp=0;
for(int x=3;x<=m;x++)
{
temp=a+b;
a=b;
b=temp;

}
return temp;
}
}


先来说说第一种递归这是一种最常见的递归 也是最好理解的,在这里我就不再赘述,原理和运行方式,只是提一句,这种递归是一种自上向下的递推过程。而它的运行时间,以及调用次数如下。






**这是当参数m为4的时候,由于此方法中只有一个m变量,在内存中运行的时候便不会占用时间和空间,这是比备忘录递归好的地方,当然这也仅仅局限于当参数m小的时候,而随着m的增大直到30,这时候显而易见备忘录递归的优势就会体现出来,这时候在方法调用和运行时间上都有明显的提升,如果说硬要有逊色的话,也就多占了一个hashmap内存空间,不过这在8GB的运行内存中显然不算什么。**


其次,再来说说备忘录递归的运行原理**



这是我在图片编辑器中以参数m=4的时候为例画出的代码流程图,里面详细的介绍了整个备忘录递归算法的运行方向,介绍了hashmap如何存值,何时存值,如果细看的话,相信收获颇丰。
最后再来说说动态规划把,关于它的定义我就不再多费口舌,简单概述,自下而上,把整个数想成一个数组,把a[0]+a[1]的值放在a[2],然后a[1]+a[2]的值放在a[3],以此类推,只要一个循环就可以得出答案了。整个方法因为没有递归的再调用,所以只被调用一次,从而大大减少了运行时间,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息