关于动态规划参考文章:
https://cloud.tencent.com/developer/article/1817113
动态规划算法的核心就是记住已经解决过的子问题的解。
动态规划有几个典型特征:最优子结构、状态转移方程、边界、重叠子问题。
什么样的问题可以考虑使用动态规划解决呢?
- 如果一个问题,可以把所有可能的答案穷举出来,并且穷举出来后,发现存在重叠子问题,就可以考虑使用动态规划。
动态规划问题的解题思路:
- 穷举分析
- 确定边界
- 找出规律,确定最优子结构
- 写出状态转移方程
动态规划的求解方式有两种:
- 自顶向下的备忘录法
- 自底向上
用这两个方法来解决一个经典的问题:斐波那契数列
方法一: 自顶向下的备忘录法
public static int fib(int n){ if(n<=0){ return n; } int[] nums=new int[n+1]; for(int i=0;i<=n;i++){ nums[i]=-1; } return fib(n, nums); } public static int fib(int n,int []nums) { if(nums[n]!=-1) {//如果不是-1,则表明n的值已经被算过不需要重新计算 return nums[n]; } if(n<=2) { nums[n] = 1; } else { nums[n]=fib( n-1,nums)+fib(n-2,nums); } return nums[n]; }
方法二: 自底向上
public static int fib(int n){ if(n == 1){ return 1; } if(n == 2){ return 2; } int[] nums = new int[n + 1];//创建一个用来保存fib第n次的结果的数组 nums[1] = 1; nums[2] = 2; for(int i = 3; i <= n; i++){ nums[i] = nums[i - 1] + nums[i - 2]; } return nums[n]; }
根据DP的解题思路,来写一下斐波那契数列问题的过程:
- 穷举分析
- 当n = 1时,f(1) = 1;
- 当n = 2时,f(2) = 2;
- 当n = 3时,f(3) = 3;
- 当n = 4时,f(4) = 5;
- 当n = 5时,f(5) = 8;
- 当n = 6时,f(6) = 13;
- 当n = 7时,f(7) = 21;
- …
-
确定边界:
根据穷举我们发现,当n大于3已经呈现出规律f(3) = f(2) + f(1) =3,因此f(1) =1,f(2) = 2就是fib的边界。 -
找出规律,确定最优子结构
明显是:f(n) = f(n-1) + f(n-2) -
写出状态转移方程
根据前面三步就可以得到状态转移方程了:if(n == 1) f(1) = 1; if(n == 2) f(2) = 2; else f(n) = f(n - 1) + f(n - 2);
例题:
- 买卖股票的最佳时机:
- 爬楼梯
- 打家劫舍
- 三道简单题
持续更新。。。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)