算法——动态规划

怼烎@ 2021-11-27 02:52 658阅读 0赞

文章目录

      • 1.斐波那契数列
        • 1.1递归法
        • 1.2动态规划
        • 1.3优化法
      • 2.变态青蛙跳台阶
      • 3.最大连续子数组和
      • 4.字符串分割
      • 5.路径总数
      • 6.路径总数(有障碍版)
      • 7.最小路径和

1.斐波那契数列

1.1递归法

  1. class Test{
  2. public int Fibonacci(int n){
  3. if(n<=0){
  4. return 0;
  5. }
  6. else if(n==1||n==2){
  7. return 1;
  8. }else
  9. return Fibonacci(n-1)+Fibonacci(n-2);
  10. }
  11. }

1.2动态规划

  1. //初始状态:f(1)=f(2)=1
  2. //状态递推:f(n)=f(n-1)+f(n-2)
  3. //返回结果:f(n)
  4. class Test{
  5. public int Fibonacci(int n){
  6. if(n<=0){
  7. return 0;
  8. }
  9. else if(n==1||n==2){
  10. return 1;
  11. }
  12. int [] a = new int [n+1];
  13. a[1]=a[2]=1;
  14. for(int i = 3;i<=n;i++){
  15. a[i]=a[i-1]+a[i-2];
  16. }
  17. return a[n];
  18. }
  19. }

1.3优化法

  1. class Test{
  2. public int Fibonacci(int n){
  3. if(n<=0){
  4. return 0;
  5. }
  6. else if(n==1||n==2){
  7. return 1;
  8. }
  9. int f1n=1;
  10. int f2n=1;
  11. int result = 0;
  12. for(int i = 3;i<=n;i++){
  13. result = f1n+f2n;
  14. f1n = f2n;
  15. f2n = result;
  16. }
  17. return result;
  18. }
  19. }

2.变态青蛙跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多 少种跳法。

方法1:
跳n级台阶,第一步有n种跳法:
跳1级,剩下n-1级,跳法为F(n-1)
跳2级,剩下n-2级,跳法为F(n-2)

跳n级,剩下0级,跳法为F(0)
So,F(n) = F(n-1)+F(n-2)+…+F(0)
F(n-1) = F(n-2)+F(n-3)+…+F(0)
F(n) = 2*F(n-2)
-
F(1) = 1
F(2) = 2
F(3) = 4

F(n) = 2^(n-1)
方法2
除了最后一级台阶必须要跳之外,其余每级台阶都有两种可能,所以F(n) = 2^(n-1)

  1. //方法1
  2. class Test{
  3. public int jumpFloor(int n){
  4. return (int)Math.pow(2,n-1);
  5. }
  6. }
  7. //方法2
  8. class Test{
  9. public int jumpFloor(int n){
  10. int total = 1;
  11. for(int i = 1;i<n;i++){
  12. total*=2;
  13. }
  14. return total;
  15. }
  16. }
  17. //方法3
  18. //降低时间复杂度 上述实现的时间复杂度:O(N) O(1)的实现:使用移位操作
  19. class Test{
  20. public int jumpFloor(int n){
  21. return 1<<(n-1);
  22. }
  23. }

3.最大连续子数组和

子状态:以a[i]为末尾元素的子数组和的最大值
f(i) = max( f(i-1)+a[i] , a[i] )
f(i) = f(i-1)>0? f(i-1)+a[i] : a[i]
初始值:f(0) = a[0]
返回值:所有f(i)中的最大值

  1. class Test{
  2. public int FindGreatestSumOfSubArray(int [] a){
  3. int sum = a[0];
  4. int maxSum = a[0];
  5. for (int i = 1;i<a.length;i++){
  6. sum = sum>0 ? (sum+a[i]):a[i];
  7. maxSum = sum>maxSum ? sum :maxSum;
  8. }
  9. return maxSum;
  10. }
  11. }

4.字符串分割

给定一个字符串s和一个词典dict,确定s是否可以根据词典中的词分成
一个或多个单词。
比如,给定
s = “leetcode”
dict = [“leet”, “code”]
返回true,因为”leetcode”可以被分成”leet code”

  1. public class Solution {
  2. public boolean wordBreak(String s, Set<String> dict) {
  3. boolean [] a = new boolean [s.length()+1];
  4. a[0] = true;
  5. for (int i = 1;i <=s.length();i++){
  6. for (int j = 0;j<i;j++){
  7. if(a[j]&&dict.contains(s.substring(j,i))){
  8. a[i]= true;
  9. break;
  10. }
  11. }
  12. }
  13. return a[s.length()];
  14. }
  15. }

5.路径总数

在一个m*n的网格的左上角有一个机器人,机器人在任何时候只能向下或者向右移动,
机器人试图到达网格的右下角,有多少可能的路径。

  1. public class Solution {
  2. public int uniquePaths(int m, int n) {
  3. int [][] a = new int [m][n];
  4. for(int i = 0;i<m;i++)
  5. a[i][0] = 1;
  6. for(int i = 0;i<n;i++)
  7. a[0][i] = 1;
  8. for(int i = 1;i<m;i++){
  9. for(int j = 1;j<n;j++){
  10. a[i][j] = a[i-1][j]+a[i][j-1];
  11. }
  12. }
  13. return a[m-1][n-1];
  14. }
  15. }

6.路径总数(有障碍版)

机器人还是要从网格左上角到达右下角, 但是网格中添加了障碍物,障碍物用1表示。

动态规划:
子状态:从(0,0)到(1,0)(1,1)…(m-1,n-1)…的路径总数
F(i,j):从(0,0)到(i,j)的路径数
状态递推:
如果(i,j)=1,则总数为0,否则为F(i-1,j)+F(i,j-1)
特殊情况:第0行及第0列:1/0

  1. public class Solution {
  2. public int uniquePathsWithObstacles(int[][] obstacleGrid) {
  3. int [][]a = new int [obstacleGrid.length][obstacleGrid[0].length];
  4. for(int i = 0;i<a.length;i++){
  5. if(obstacleGrid[i][0] == 1){
  6. break;
  7. }
  8. a[i][0] = 1;
  9. }
  10. for(int i = 0;i<a[0].length;i++){
  11. if(obstacleGrid[0][i] == 1){
  12. break;
  13. }
  14. a[0][i] = 1;
  15. }
  16. for(int i = 1;i<a.length;i++){
  17. for(int j = 1;j<a[0].length;j++){
  18. if(obstacleGrid[i][j] == 1){
  19. a[i][j] = 0;
  20. }else{
  21. a[i][j] = a[i-1][j]+a[i][j-1];
  22. }
  23. }
  24. }
  25. return a[a.length-1][a[0].length-1];
  26. }
  27. }

7.最小路径和

给定一个m*n的网格,网格用非负数填充,找到一条从左上角到右下角的短路径。 注:每次只能向下或者向右移动。

  1. public class Solution {
  2. public int minPathSum(int[][] grid) {
  3. int [][]a = new int[grid.length][grid[0].length];
  4. a[0][0] = grid[0][0];
  5. for(int i=1;i<grid.length;i++){
  6. a[i][0] = a[i-1][0]+grid[i][0];
  7. }
  8. for(int i=1;i<a[0].length;i++){
  9. a[0][i] = a[0][i-1]+grid[0][i];
  10. }
  11. for(int i=1;i<a.length;i++){
  12. for(int j=1;j<a[0].length;j++){
  13. a[i][j] = Math.min(a[i-1][j],a[i][j-1])+grid[i][j];
  14. }
  15. }
  16. return a[a.length-1][a[0].length-1];
  17. }
  18. }

发表评论

表情:
评论列表 (有 0 条评论,658人围观)

还没有评论,来说两句吧...

相关阅读

    相关 动态规划算法

    一:动态规划算法 1:动态规划算法介绍 1) 动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决,从而一步步获

    相关 动态规划算法

           动态规划方法是对解最优问题的一种方法,一种途径,并不是一种特殊的算法。        执行步骤:                1. 找出最优解的性质,刻画结