动态规划常见问题

这个也是通过看视频来总结的两个类型的问题关于动态规划问题

1.动态规划之选数问题

题目要求:

假设给定一串数字{1, 2, 4, 1, 7, 8, 3},我们要从中选择若干个数,使最后的和达到最大。选择的规则是,不能选相邻的数字。比如:如果我们选了第一个数字1,那么我们就不能选2,如果我们选择了数字4,那么我们就不能选择与它相邻的2和1。

动态规划的思想:将整个问题划分成一个个子问题,也就是说要求整个数列的最大和,可以先求出前面若干个数的和,一直划分到求出只有一个数的最大和(即本身),而每个子问题的解对于后面的结果都是有用的,这就是用到了动态规划的思想

思路:

对于每个数,都有选和不选两种状态,如果选了这个数,那么就不能选他相邻的那个数,那么最大和就等于本身加上他相邻的那位数之前那些数的最大和,如果不选这个数,那么便可以选它相邻的那个数,那么最大和就等于这个数之前的那些数的最大和。最终的结果就是取这两种选择的最大值

这里就可以使用递归,即Math.max(dp(arr, x-2)+arr[x], dp(arr, x-1));

递归的出口:

如果只有一个数,那么最大和就是本身
如果只有两个数,那么最大和就是这两个数中的最大值
 

public static int dp(int[] arr){
    int[] temp=new int[arr.length];
    temp[0]=arr[0];
    temp[1]=Math.max(arr[0], arr[1]);
    for(int i=2;i<arr.length;i++){
        temp[i]=Math.max(temp[i-2]+arr[i],temp[i-1]);
    }
    return temp[arr.length-1];
}

2. 动态规划之最长公共子序列

题目描述:

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的公共子序列是这两个字符串所共同拥有的子序列。

若这两个字符串没有公共子序列,则返回 0。
 

public static int longestCommonSubsequence(String text1, String text2) {
    int len1=text1.length();
    int len2=text2.length();
    char[] ch1=text1.toCharArray();
    char[] ch2=text2.toCharArray();

    //动态规划算法创建的二维数组一般都得多增一行一列,这是为了防止数组越界异常
    int[][] p=new int[len1+1][len2+1];

    //填表,第一行和第一列都为0,所以填表从下标为1的行和下标为1的列开始填
    for(int i=1;i<p.length;i++){
        for(int j=1;j<p[0].length;j++){
            if(ch1[i-1]==ch2[j-1]){
                p[i][j]=p[i-1][j-1]+1;
            }else{
                p[i][j]=Math.max(p[i-1][j], p[i][j-1]);
            }
        }
    }	
    return p[len1][len2];
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值