代码随想录算法训练营第四十二天|1049. 最后一块石头的重量II、494. 目标和、474. 一和零

LeetCode 1049. 最后一块石头的重量II
题目链接:1049. 最后一块石头的重量 II - 力扣(LeetCode)

我们两部分考虑,一部分是正的,一部分是负的,这道题是想求最平衡的时候

每道题都要考虑dp五步:

1)确定dp数组下标与值的关系:其实就是求离target最近的一个和

2)确定递推公式:一维数组,所以从后向前,这样对于每个物品只会放一次。

3)确定初始值:dp[0][0]肯定是0,一点空间也没,一件物品也没,当然价值为0

4)确定遍历的数:

5)带入验证一下

代码:

#python   一维数组
class Solution:
    def lastStoneWeightII(self, stones: List[int]) -> int:
        total_sum = sum(stones)
        target = total_sum // 2
        dp = [0 for _ in range(target + 1)]   //一维数组
        dp[0] = 0
        for stone in stones:  //先遍历重量
            for j in range(target, stone - 1, - 1):
                dp[j] = max(dp[j], dp[j - stone] + stone)  //比一比当前最大能装多少
        return total_sum - 2 * dp[-1] //最后一个是最接近与中和的数

LeetCode 494. 目标和
题目链接:494. 目标和 - 力扣(LeetCode)

第一反应是一个DFS,回溯法,但是就别回了,直接DP,我们可以不断赋值,得到一个最大的表达式数组。

每道题都要考虑dp五步:

1)确定dp数组下标与值的关系:同样的就是求离target最近的一个和

2)确定递推公式:一维数组,所以从后向前,这样对于每个物品只会放一次。

3)确定初始值:dp[0]应该为1,此时只有一种选择

4)确定遍历的数:内循环从大到小

5)带入验证一下

代码:

#python
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        total_sum = sum(nums)  # 计算nums的总和
        if abs(target) > total_sum:
            return 0  # 此时没有方案
        if (target + total_sum) % 2 == 1:
            return 0  # 此时没有方案
        target_sum = (target + total_sum) // 2  # 目标和
        dp = [0] * (target_sum + 1)  # 创建动态规划数组,初始化为0
        dp[0] = 1  # 当目标和为0时,只有一种方案,即什么都不选
        for num in nums:
            for j in range(target_sum, num - 1, -1):
                dp[j] += dp[j - num]  # 状态转移方程,累加不同选择方式的数量
        return dp[target_sum]  # 返回达到目标和的方案数  
/java
class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int total_sum = 0;
        for(int num : nums){
            total_sum += num;
        }
        if(Math.abs(target) > total_sum){
            return 0;
        }        
        if((target + total_sum) % 2 == 1){
            return 0;
        }
        int target_sum = (target + total_sum) / 2;
        int[] dp = new int[target_sum + 1];
        dp[0] = 1;
        for(int num : nums){
            for(int i = target_sum; i >= num; i--){
                dp[i] += dp[i - num];
            }
        }
        return dp[target_sum];
    }
}

LeetCode 474. 一和零
题目链接:474. 一和零 - 力扣(LeetCode)

这道题感觉也是DFS,我们用DP来做,思路就是遍历所有的str,使用collections里的counter来计算一下1与0的个数,随后我们用一个二维数组dp[i][j]来得到一个子集元素最多的满足条件的子集,(i表示1的个数,j表示0的个数)。

每道题都要考虑dp五步:

1)确定dp数组下标与值的关系:

2)确定递推公式:二维数组,赋值的时候都是0,后面要求最大的,因此要么是当前的个数,要么是从前来的(dp[i - one_num][j - zero_num]从这里推过来,当然个数就要+1)

3)确定初始值:dp[0]应该为0

4)确定遍历的数:都是逆向的,其实这和前面的题目有点像,像两个内循环

d5)带入验证一下

代码:

#python
class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        dp = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
        for st in strs:
            one_num = st.count('1')  //1的个数
            zero_num = len(st) - one_num  //0的个数
            for i in range(m, zero_num - 1, -1):   //逆向
                for j in range(n, one_num - 1, - 1):   //逆向
                    dp[i][j] = max(dp[i][j], dp[i - zero_num][j - one_num] + 1)
        return dp[m][n]
/java
class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        int[][] dp = new int[m + 1][n + 1];
        for(String str : strs){
            char[] words = str.toCharArray();
            int one_sum = 0, zero_sum = 0;
            for(char word : words){
                if(word == '1'){
                    one_sum++;
                }else{
                    zero_sum++;
                }
            }
            for(int i = m; i >= zero_sum; i--){
                for(int j = n; j >= one_sum; j--){
                    dp[i][j] = Math.max(dp[i][j], dp[i - zero_sum][j - one_sum] + 1);
                }
            }
        }
        return dp[m][n];
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别看了真C不了一点

打赏者皆为义父

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值