DP动态规划+贪心题目汇总

背包

01背包

[图片]

416. 分割等和子集

//f[i][j]表示能否从 nums中前i个 选出一个和恰好等于 j 的子序列.这不就是01背包
f[i][j] = f[i-1][j - nums[i]] || f[i-1][j] 选和不选
01背包优化成一维形式,i维度不要,内层循环从target递减
也可以用记忆化搜索做

class Solution {
   
    public boolean canPartition(int[] nums) {
   
        //f[i][j]表示能否从 nums中前i个 选出一个和恰好等于 j 的子序列.这不就是01背包
        //f[i][j] = f[i-1][j - nums[i]] || f[i-1][j] 选和不选
        //01背包优化成一维形式,i维度不要,内层循环从target递减
        int n = nums.length;
        int target = 0;
        for(int i = 0; i < n; i ++)
            target += nums[i];
        if(target % 2 != 0) return false;
        target /= 2;
        boolean[] f = new boolean [target+1];
        f[0] = true;
        for(int i = 1; i <= n; i ++) {
   
            for(int j = target; j >= nums[i-1]; j --) {
   
                f[j] = f[j - nums[i-1]] || f[j];
            }
        }
        return f[target];
    }
}

完全背包

在这里插入图片描述

外层是物品(数组)遍历,内层是限制(容量价值)遍历

279. 完全平方数

在这里插入图片描述

完全背包问题

class Solution {
   
    public int numSquares(int n) {
   
        int[] f = new int[n+1];
        f[1] = 1;  
        for(int i = 1; i <= n; i ++) {
   
            f[i] = i; // 最坏的情况就是每次+1
            for(int j = 1 ;j <= n; j ++)
                if(i >= j*j)
                    f[i] = Math.min(f[i], f[i - j*j] + 1);
        }
        return f[n];
    }
}

322. 零钱兑换

在这里插入图片描述

也是完全背包问题

for(int i = 1; i <= n; i ++ ) {
   
    for(int j = c[i-1]; j <= amount; j ++) {
   
        dp[j] = Math.min(dp[j], dp[j-c[i-1]] + 1);
    }
}

Arrays.fill(dp, amount + 1); //因为是最小值,初始化0会一直是0

class Solution {
   
    public int coinChange(int[] c, int amount) {
   
        //dp[i]:表示最小个数
        //dp[j] = min(dp[j], dp[j-c[i]] + 1)
        int n = c.length;
        int[] dp = new int[amount + 1];
        Arrays.fill(dp, amount + 1); //因为是最小值,初始化0会一直是0
        dp[0] = 0;
        for(int i = 1; i <= n; i ++ ) {
   
            for(int j = c[i-1]; j <= amount; j ++) {
   
                dp[j] = Math.min(dp[j], dp[j-c[i-1]] + 1);
            }
            
        }
        int ans = dp[amount];
        return ans < amount + 1 ? ans : -1;
    }
}

两个字符串DP

LCR 095. 最长公共子序列

在这里插入图片描述

class Solution {
   
    public int longestCommonSubsequence(String text1, String text2) {
   
    //设 f(i,j)表示第一个字符串的前 i个字符和第二个字符串的前 j个字符的最长公共子序列
        //dp[i][j] = max(dp[i-1][j], dp[i][j-1],dp[i-1][j-1] + 1) 或者 max(dp[i-1][j], dp[i][j-1])
        //忽略text1[i]或者忽略text2[j]
        //这个是 求两个字符串的公共子序列,不需要len 不是遍历len对len分1 2 更长的情况的
        int n = text1.length(), m = text2.length();
        int[][] dp = new int [n+1][m+1];
        int ans = 0;
        for(int i = 1; i <= n; i ++) {
   
            for(int j = 1; j <= m; j ++) {
   
                if(Objects.equals(text1.charAt(i-1),text2.charAt(j-1))) 
                    dp[i][j] = Math.max(Math.max(dp[i-1][j], dp[i][j-1]),dp[i-1][j-1] + 1);
                else 
                    dp[i][j] = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值