Leetcode 刷题 动态规划

1049. 最后一块石头的重量 II

 其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小

这样就化解成01背包问题了

class Solution {
    public int lastStoneWeightII(int[] stones) {
        int sum = 0;
        for(int stone : stones){
            sum += stone;
        }
        int target = sum / 2;
        int[] dp = new int[target + 1];

        for(int i = 0; i < stones.length; i++){
            for(int j = target; j >= stones[i]; j--){
                dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
            }
        }

        return Math.abs(dp[target] - (sum - dp[target]));
    }
}
494. 目标和

转化为01背包问题

问题转化为,装满容量为x的背包,有几种方法 

这次和之前遇到的背包问题不一样了,之前都是求容量为j的背包,最多能装多少。

1.确定dp数组的含义

        dp[j] 表示:填满j(包括j)这么大容积的包,有dp[j]种方法

2.递推关系

        只要搞到nums[i],凑成dp[j]就有dp[j - nums[i]] 种方法

dp[j] += dp[j - nums[i]]

 3. dp数组如何初始化

     从递推公式可以看出,在初始化的时候dp[0] 一定要初始化为1,因为dp[0]是在公式中一切递推结果的起源

4. 确定遍历顺序

        nums放在外循环,target在内循环,且内循环倒序   

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int sum = 0;
        for(int num : nums){
            sum += num;
        }
        if((sum + target) % 2 != 0){
            return 0;
        }
        if (target < 0 && sum < -target) return 0;
        int goal = (sum + target) / 2;

        if(goal < 0){
            goal = -goal;
        }

        int[] dp = new int[goal + 1];
        dp[0] = 1;

        for(int i = 0; i < nums.length; i++){
            for(int j = goal; j >= nums[i]; j--){
                dp[j] += dp[j - nums[i]];
            }
        }

        return dp[goal];

    }
}

        

474. 一和零

但本题其实是01背包问题!

只不过这个背包有两个维度,一个是m 一个是n,而不同长度的字符串就是不同大小的待装物品。

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        int[][] dp = new int[m + 1][n + 1];

        for(String str : strs){
            int oneNum = 0;
            int zeroNum = 0;
            char[] chars = str.toCharArray();
            for(char c : chars){
                if(c == '0'){
                    zeroNum++;
                }
                if(c == '1'){
                    oneNum++;
                }
            }
            for(int i = m; i >= zeroNum; i--){
                for(int j = n; j >= oneNum; j--){
                    dp[i][j] = Math.max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
                }
            }
        }
        return dp[m][n];

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值