算法与数据结构-动态规划 讲解与java代码实现

1. 从暴力搜索到记忆搜索,再到动态规划

这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述

2. 找零问题

有数组penny,penny中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。
给定数组penny及它的大小(小于等于50),同时给定一个整数aim,请返回有多少种方法可以凑成aim。
测试样例:
[1,2,4],3,3
返回:2

import java.util.*;
//动态规划方法求解给定数额求找零方法的总数 是用空间换时间 时间复杂度为O(n*aim) 下一层方法总是枚举上一层的方法
public class Exchange {
    public int countWays(int[] penny, int n, int aim) {
        int[] dp=new int[aim+1];
        dp[0]=1;//得到0值的方法对任何面值的组合来说都只有一种
        for(int i=0;i<n;i++){
            for(int j=penny[i];j<=aim;j++){
                dp[j]+=dp[j-penny[i]];
            }
        }
        return dp[aim];
    }
}

3. 台阶问题

有n级台阶,一个人每次上一级或者两级,问有多少种走完n级台阶的方法。为了防止溢出,请将结果Mod 1000000007
给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。
测试样例:
1
返回:1

import java.util.*;
//每次只能走1或者2步,求走完n个台阶的方法数 倒推使用f(i)=f(i-1)+f(i-2)的方法
public class GoUpstairs {
    public int countWays(int n) {
        /*if(n<1){
            return 0;
        }
        if(n==1||n==2){
            return n;
        }

        return (count(n-1)+count(n-2))%1000000007;
       */ //为什么数组越界?
        int[] res=new int[300030];//大小如何确定的?
        res[0]=1;
        for(int i=1;i<=n;i++){
            res[i]=((i>=1?res[i-1]:0)+(i>=2?res[i-2]:0))%1000000007;
        }
        return res[n];
    }

}

4. 格子最短路径问题

这里写图片描述

import java.util.*;
//格子最短路径求解
public class MinimumPath {
    public int getMin(int[][] map, int n, int m) {
        int[][] dp=new int[n][m];
        dp[0][0]=map[0][0];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(i==0&&j==0){
                    continue;
                }
                dp[i][j]=map[i][j]+Math.min((i>=1?dp[i-1][j]:dp[0][j-1]),(j>=1?dp[i][j-1]:dp[i-1][0]));
            }
        }

        return dp[n-1][m-1];
    }
}

5. LIS最大递增子序列

这里写图片描述

import java.util.*;
//数组最长上升自序列问题
public class LongestIncreasingSubsequence {
    public int getLIS(int[] A, int n) {
        int[] dp=new int[n];
        int totalMax=0;
        for(int i=0;i<n;i++){
            int max=0;
            for(int j=i-1;j>=0;j--){
               if(dp[j]>max&&A[j]<A[i]){
                   max=dp[j];
               }
            }
            dp[i]=1+max;
            if(dp[i]>totalMax){
                totalMax=dp[i];
            }
        }
        return totalMax;
    }
}

6. LCS公共最长子序列

这里写图片描述

import java.util.*;
//公共最长子序列求解
public class LCS {
    public int findLCS(String A, int n, String B, int m) {
       int[][] dp=new int[n][m];
        //处理第0行,只要B[i]==A[0] 那么B[i+1,...m]都为1
        boolean rFlag=false;
         for(int j=0;j<m;j++){
             if(A.charAt(0)==B.charAt(j)||rFlag==true){
                 dp[0][j]=1;
                 rFlag=true;
            }
         }

        boolean cFlag=false;
        for(int i=0;i<n;i++){
            if(B.charAt(0)==A.charAt(i)||cFlag){
                dp[i][0]=1;
                cFlag=true;
            }
        }

        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){    
                if(A.charAt(i)==B.charAt(j)){
                    dp[i][j]=dp[i-1][j-1]+1;
                }else{
                    dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }

        return dp[n-1][m-1];
    }
}

7. 背包问题

这里写图片描述

import java.util.*;
//背包问题
public class Backpack {
    public int maxValue(int[] w, int[] v, int n, int cap) {
        int[][] dp=new int[n][cap+1];
        //处理第一个物品的价值
        for(int column=0;column<=cap;column++){
            if(column>=w[0]){
                dp[0][column]=v[0];
            }
        }

        for(int i=1;i<n;i++){
            for(int j=1;j<=cap;j++){
                int a=dp[i-1][j];
                int b=0;
                if((j-w[i])>=0){
                   b=dp[i-1][j-w[i]]+v[i];
                }
                dp[i][j]=Math.max(a,b);
            }
        }

        return dp[n-1][cap];
    }
}

8. 编辑字符串最小代码问题

这里写图片描述
这里写图片描述

import java.util.*;
//最优编辑问题
public class MinCost {
    public int findMinCost(String A, int n, String B, int m, int c0, int c1, int c2) {
        int[][] dp=new int[n+1][m+1];

        //处理第一列,即删除0-i-1的字符变到空串的代价,为c1*i
        for(int i=1;i<=n;i++){
            dp[i][0]=c1*i;
        }

        //处理第一行,即增加0-j-1个字符编导B串的代价,为c0*j
        for(int j=0;j<=m;j++){
            dp[0][j]=c0*j;
        }

        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int a=dp[i-1][j]+c1;
                int b=dp[i][j-1]+c0;
                int c=(A.charAt(i-1)==B.charAt(j-1)?dp[i-1][j-1]:(dp[i-1][j-1]+c2));

                dp[i][j]=Math.min(Math.min(a,b),c);
            }
        }
        return dp[n][m];
    }
}

9. JAVA

*     java要获取字符串中的单个字符 S.charAt(index),不能使用S[index]方式
*     Math.min(a,b)只接受两个数,如果要比较三个数,可以采用Math.min(Math.min(a1,a2),a3)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值