算法:动态规划
Posted lzy321
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法:动态规划相关的知识,希望对你有一定的参考价值。
基本内容:
这几天学习了一下动态规划,特此整理。
在一道题中反复使用或者反复计算,将重复的内容存到一个集合里面,计算后面的时候直接从集合里面取值,可以大幅优化时间和空间。
核心:记住求过的解来节省时间。
例:
计算:1+1+1+1+1
结果 不使用动态规划加五次得到 5
计算:给上面式子加一
结果:使用动态规划:计算过程为取上面结果,给结果加1,只进行一次计算。(很快就能计算出来)
动态规划有两种形式:
1.自顶向下的备忘录法(空间复杂度高)
2.自底向上(推荐)
为了说明两种方法:举一个简单例子:
斐波那契数列:1 1 2 3 5 8 13 ...........
Fibonacci(n) = 1; n = 0;
Fibonacci(n) = 1; n = 1;
Fibonacci(n) = 1; n = Fibonacci(n-1) + Fibonacci(n-2) ;
自顶向下(递归):
1 public class DP{ 2 public static int f(int n){ 3 if(n==0){ 4 return 1; 5 } 6 if(n==1){ 7 return 1; 8 } 9 return f(n-1)+f(n-2); 10 } 11 public static void main(String args[]){ 12 int n=5; 13 f(n); 14 } 15 }
这个复杂度是一个树形结构,十分复杂,O(2^n)
如果将f(0),f(1),f(2).......存入表中,如果计算时,算过就从表中直接取.
自顶向下(递归)动态规划(备忘录法)(因为使用了递归,所以空间复杂度较高)
简单来说就是使用一个数组或者集合或者其他,将已经计算过的值存在里面,计算的时候,先查看这个位置的值有没有被计算过,有就返回,没有就计算。
这里的数组就相当于一个备忘录
1 public class DP{ 2 public static void main(String args[]){ 3 int n=5; 4 int[] bak=new int[n+1]; 5 for(int i=0;i<n+1;i++){ 6 bak[i]=-1; 7 } 8 System.out. println(f(n,bak)); 9 } 10 public static int f(int n,int[] bak){ 11 if(n==0){ 12 return 1; 13 } 14 if(n==1){ 15 return 1; 16 } 17 if(bak[n] !=-1){ 18 return bak[n]; 19 } 20 int result =f(n-1,bak)+f(n-2,bak); 21 bak[n]=result; 22 return result; 23 } 24 25 }
自底向上:
就是说不使用数组,使用两个值r1,r2,代表r1,r2,从最开始向目标计算
1 public class Main{ 2 public static void main(String args[]){ 3 int n=5; 4 System.out. println(f(n)); 5 } 6 public static int f(int n){ 7 if(n==0){ 8 return 1; 9 } 10 if(n==1){ 11 return 1; 12 } 13 int result = 0; 14 int r1=1; 15 int r2=1; 16 for(int i=2;i<=n;i++){ 17 result= r1 + r2; 18 r1=r2; 19 r2=result; 20 } 21 return result; 22 } 23 24 }
以上是关于算法:动态规划的主要内容,如果未能解决你的问题,请参考以下文章
算法动态规划 ⑤ ( LeetCode 63.不同路径 II | 问题分析 | 动态规划算法设计 | 代码示例 )
算法动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 )