动态规划
引入
斐波那契数列
Java程序运行时间计算:
long startTime = System.currentTimeMillis(); //获取开始时间
method(); //测试的代码段
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms"); //输出程序运行时间
递归法计算斐波那契数列
代码
package 动态规划--递归法;
public class Solution {
public static int fib(int n){
//编写斐波那契数列的计算
if(n == 0){
return 0;
}else if(n == 1){
return 1;
}else {
return fib(n-1)+fib(n-2);
}
}
public static void main(String[] args) {
int n = 40;
//获取开始的时间
long starttime = System.currentTimeMillis();
int res = fib(n);
long endtime = System.currentTimeMillis();//获取结束时间
System.out.println(res);
System.out.println("程序运行时间为:"+ (endtime-starttime)+"ms");
}
}
运行结果:
存在的效率问题
大家看图可以发现,里面存在大量重复元素的计算,是否有一种办法能让程序只计算一次,第二次出现相同元素的时候直接调用。
记忆搜索算法–自上向下的解决问题
优化:避免重复元素的计算。使用一个数组来记忆对应递归值,数组初始化默认为0,因此判断不等于0,递归中若能在数组中找到对应值则直接取用。
tip:创建数组时一定要length+1,因为数组从0开始。避免取最后值时越界。
代码
package 动态规划;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
import java.util.Vector;
public class Solution {
static int c;
static int[] memo;
public static int fib(int n){
return fib(n,new int[n+1]);
}
private static int fib(int n,int[] m){
c++;
if(n == 0){
return 0;
}else if(n == 1){
return 1;
}else if(m[n] !=0) {
return m[n];
}else {
return m[n] = fib(n-1,m)+fib(n-2,m);
}
}
public static void main(String[] args) {
int n = 40;
//获取开始的时间
long starttime = System.currentTimeMillis();
int res = fib(n);
long endtime = System.currentTimeMillis();//获取结束时间
System.out.println(res);
System.out.println("程序运行时间为:"+ (endtime-starttime)+"ms");
System.out.println("程序运行"+ c + "次");
}
}
效率提高
动态规划–自下而上的解决问题
动态规划:就是将一个庞大的问题拆解成一个小问题,同时保存子问题的答案,使每个子问题只求解一次,最终得到原问题的答案。
代码
package 动态规划;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
import java.util.Vector;
public class Solution {
static int c;
static int[] memo;
public static int fib(int n){
return fib(n,new int[n+1]);
}
private static int fib(int n,int[] m){
//动态规划
m[0] = 0;
m[1] = 1;
for (int i = 2; i <= n; i++) {
c++;
m[i] = m[i-1]+m[i-2];
}
return m[n];
}
public static void main(String[] args) {
int n = 40;
//获取开始的时间
long starttime = System.currentTimeMillis();
int res = fib(n);
long endtime = System.currentTimeMillis();//获取结束时间
System.out.println(res);
System.out.println("程序运行时间为:"+ (endtime-starttime)+"ms");
System.out.println("程序运行"+ c + "次");
}
}