20240315-动态规划

例题1 使用最小花费爬楼梯

https://leetcode.cn/problems/min-cost-climbing-stairs/description/

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        int[] dp= new int[n+1];
        for(int i=2;i<n+1;i++){
            dp[i]=Math.min(dp[i-2]+cost[i-2],dp[i-1]+cost[i-1]);
        }
        return dp[n];
    }
}

例题2不同路径

https://leetcode.cn/problems/unique-paths/description/

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];
        //初始化
        for(int i=0;i<m;i++)dp[i][0]=1;
        for(int j=0;j<n;j++)dp[0][j]=1;
        //循环
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];

    }
}

例题3 整数拆分

class Solution:
    def integerBreak(self, n: int) -> int:
        dp=[1 for _ in range(n+1)]
        for i in range(3,n+1):
            for j in range(1,i):
                dp[i]=max(dp[i],j*(i-j),j*dp[i-j])
        return dp[n]

例题4 不同的二叉搜索树

class Solution {
    public int numTrees(int n) {
        int[] dp=new int[n+1];
        dp[0]=1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++){
                dp[i]+=(dp[j-1]*dp[i-j]);
            }
        }
        return dp[n];

    }
}

例题5 01背包

  • dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。

  • 那么可以有两个方向推出来dp[i][j],

    不放物品i:由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同。)
    放物品i:由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值

所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

  • 初始化:
    dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包所能存放的最大价值。
    当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。
    当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。

  • 滚动数组
    表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);
    dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少
    dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

    • 背包容量是从小到大,目的是 倒序遍历是为了保证物品i只被放入一次
for(int i = 1; i < weight.size(); i++) { // 遍历物品
    for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
        if (j < weight[i]) dp[i][j] = dp[i - 1][j];
        else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

    }
}
for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

    }
}

例题6 分割等和子集

https://leetcode.cn/problems/partition-equal-subset-sum/description/

class Solution {
    public boolean canPartition(int[] nums) {
        int n= nums.length;
        if(n<2)return false;
        int sum=0,maxNum=0;
        for(int num:nums){
            sum+=num;
            maxNum=Math.max(maxNum,num);
        }
        if(sum%2 != 0)return false;
        int target=sum/2;
        if(maxNum>target)return false;
        int[][] dp=new int[n][target+1];
        //初始化
        for(int j=nums[0];j<=target;j++){
            dp[0][j]=nums[0];
        }
        for(int i=1;i<n;i++){ //循环物品
            for(int j=0;j<=target;j++){
                if(j>=nums[i])dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i]);
                else dp[i][j]=dp[i-1][j];
            }
        }
        return dp[n-1][target]==target;


    }
}

例题7 最后一块石头的重量 II

https://leetcode.cn/problems/last-stone-weight-ii/description/

class Solution:
    def lastStoneWeightII(self, stones: List[int]) -> int:
        V=(sum(stones)//2)+1
        n=len(stones)
        dp=[[0 for _ in range(V)] for _ in range(n)]
        #初始化
        for j in range(stones[0],V):
            dp[0][j]=stones[0]
        #循环
        for i in range(1,n):
            for j in range(V):
                if j>=stones[i]:
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-stones[i]]+stones[i])
                else:
                    dp[i][j]=dp[i-1][j]
        return sum(stones)-2*dp[-1][-1]

例题8 目标和 ****

https://leetcode.cn/problems/target-sum/description/
left-right=target
left+right=sum
left=(target+sum)/2


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值