1049.最后一块石头的重量II,494.目标和,474.一和零

代码随想录训练营第43天|1049.最后一块石头的重量II,494.目标和,474.一和零

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

文章

[代码随想录|1049.最后一块石头的重量]https://programmercarl.com/1049.%E6%9C%80%E5%90%8E%E4%B8%80%E5%9D%97%E7%9F%B3%E5%A4%B4%E7%9A%84%E9%87%8D%E9%87%8FII.html()

思路

石头分成两组,以总重量一半为背包容量,求最多容纳石头的重量为较小一组,从总重量中减去较小一组的重量为较大一组重量,两组重量只差即为所求。

代码

class Solution {
    public int lastStoneWeightII(int[] stones) {
        int sum = 0;
        int i, j, n;
        n = stones.length;
        for (i = 0; i < n; ++i) {
            sum += stones[i];
        }
        int capacity = sum >> 1;
        int[] dp = new int[capacity + 1];
        for (i = 0; i < capacity + 1; ++i) {
            dp[i] = stones[0] > i ? 0 : stones[0];
        }
        for (i = 1; i < n; ++i) {
            for (j = capacity; j > 0; --j) {
                if (j >= stones[i]) {
                    dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
                }
            }
        }
        return sum - (dp[capacity] << 1);
    }
}

494.目标和

文章

代码随想录|0494.目标和

思路

分成两组,一组加号,另一组减号,加号组之和应为 s u m + t a r g e t 2 \frac{sum+target}{2} 2sum+target,因此如果不整除则直接返回0
用dp数组,dp[i]表示加号组在当前求和正好为i的方案数

代码

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int i, j, n, sum;
        n = nums.length;
        sum = 0;
        for (i = 0; i < n; ++i) {
            sum += nums[i];
        }
        if ((sum + target) % 2 != 0 || sum + target < 0) {
            return 0;
        }
        int pos = sum + target >> 1;
        int[] dp = new int[pos + 1];
        for (j = 0; j < pos + 1; ++j) {
            dp[j] = nums[0] == j ? 1 : 0;
        }
        dp[0] += 1;
        for (i = 1; i < n; ++i) {
            for (j = pos; j > -1; --j) {
                
                if (j >= nums[i]) {
                    dp[j] += dp[j - nums[i]];
                }
                // if (j == pos)
                //     System.out.println(dp[j]);
            }
        }
        return dp[pos];
    }
}

474.一和零

文章

代码随想录|0474.一和零

思路

不得不用二维数组了
dp[i][j]表示0和1数量分别限制为i和j时的最大子集规模

代码

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        int i, j, k, num;
        int nz, no;
        num = strs.length;
        int[][] dp = new int[m + 1][n + 1];
        for (i = 0; i < num; ++i) {
            nz = count(strs[i], '0');
            no = count(strs[i], '1');
            if (nz <= m && no <= n) {
                for (j = m; j >= nz; --j) {
                    for (k = n; k >= no; --k) {
                        dp[j][k] = Math.max(dp[j - nz][k - no] + 1, dp[j][k]); 
                    }
                }
            }
        }
        return dp[m][n];
    }

    public int count (String str, char tar) {
        int res = 0;
        char ch;
        int i, n;
        n = str.length();
        for (i = 0; i < n; ++i) {
            if (str.charAt(i) == tar) {
                ++res;
            }
        }
        return res;
    }
}

总结

二刷,还需熟练,小错误一堆

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值