2021-12-3 63. 不同路径 II 343. 整数拆分 416. 分割等和子集

这篇博客介绍了如何使用动态规划解决三个经典问题:不同路径II、整数拆分和分割等和子集。在不同路径II中,通过初始化二维数组来跟踪从起点到终点的不同路径数量,避开障碍物。整数拆分问题中,博主展示了如何建立状态转移方程找到将整数拆分成若干个因子的乘积最大值。分割等和子集问题中,博主讨论了如何判断一个数组能否被分割成两个和相等的子集,以及如何优化解决方案。

63. 不同路径 II


class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int n = obstacleGrid.length;
        int m = obstacleGrid[0].length;
        int[][] dp = new int[n][m];
        //刚开始对第一行和第一列的数据赋初始时值1时要注意,只要这一行某个位置出现了障碍,该行后续的数据都不能走了,即赋值为0。
        for(int i=0;i<n;i++){
            if(obstacleGrid[i][0] == 1) break; 
            dp[i][0] = 1;
        }
        for(int j=0;j<m;j++){
            if(obstacleGrid[0][j] == 1) break;  
            dp[0][j] = 1;
        }
        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                if(obstacleGrid[i][j] == 1){
                    continue;
                }
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[n-1][m-1];
    }
}

343. 整数拆分

class Solution {
    public int integerBreak(int n) {
        if(n == 2) return 1;
        //做时不能看出其为动态规划
        //dp[i]表示数字i划分后得到的最大乘积
        int[] dp = new int[n+1];
        dp[0] = 0;
        //dp[1] = 1;
        dp[2] = 1;
        //对递归过程没理解透彻,第一层循环表示对第i个数进行划分,
        //第二层循环表示以哪个数进行其中的划分
        for(int i=3;i<n+1;i++){  
            for(int j=1;j<n;j++){
                //注意:这里选取最大值的比较还包括dp[i]
    dp[i] = Math.max(dp[i],Math.max(dp[j]*(i-j),j*(i-j)));
            }
            //dp[i] = Math.max((n-i+1) * dp[i-1],(n-i+1)*(i-1));  
        }
        return dp[n];
    }
}

416. 分割等和子集

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for(int i=0;i<nums.length;i++){
            sum+=nums[i];
        }
        if(sum%2 != 0) return false;
        sum = sum/2;
 //错误原因:不能将其转换为01背包去做
//dp[i]表示背包容量为i时的价值(此题的物品即数组中的数,价值即所谓的和)
        int[] dp = new int[sum+1];
        for(int i=0;i<nums.length;i++){
            for(int j=sum;j>=nums[i];j--){
                dp[j] = Math.max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        return dp[sum] == sum;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值