leetcode416.分割等和子集(中等)

在这里插入图片描述
在这里插入图片描述
思路:01背包问题(从右向左写)
题目可以转化为:在nums数组中找出一些元素,这些元素的和为sum/2,由于每个元素只能选一次,所以等价于0-1背包问题(传统的01背包的限制是背包容量有限,这道题的限制是和为固定值)
具体细节
dp[i][j]表示:下标i前面所有的元素是否能组成j
转移方程:dp[i][j] = dp[i - 1][j - nums[i]] || dp[i - 1][j] (选nums[i] 不选nums[i] 两个中有一个构成即可,所以用逻辑运算符’||')
边界:dp[0][0] = true 其他都是false
特例判别
1:数组中所有元素的和sum为奇数时 return false
2:数组中只有一个元素时 return false
3:数组中元素的最大值 大于 sum/2 return false

class Solution {
public:
    bool canPartition(vector<int>& nums) {
 
        int sum = accumulate(nums.begin(), nums.end(), 0), n = nums.size();
        if (sum & 1 || n < 2) return false;
        if (*max_element(nums.begin(), nums.end()) > sum / 2) return false;
        vector<int> dp(sum / 2 + 1, false);
        dp[0] = true;
        for (int i = 0; i < n; ++i) {
            for (int j = sum / 2; j >= nums[i]; --j) {
                dp[j] = dp[j - nums[i]] || dp[j];
            }
        }
        return dp[sum / 2];
    }
};

思路2:hash
易错点:在遍历hash时,要先备份原hash一份:hash2,在hash2上面遍历,插入到hash。因为在同一个hash里面操作的话可能会导致迭代器失效

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值