dp专题7 分割等和子集

本题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

题目:

思路:

由题意,题目意思是给出  数组 nums  找出两个子集它们的元素和相等。

这里两个自己的元素和相等,说明需要 数组 nums 总和可以平分,即 sum % 2 == 0

又因为子集不要求我们所取的元素是连续的,这里只有取或不取,所以我们试着取联想以下 01 背包

其中 容量是 我们的 sum / 2 ,只要我们取的 nums 元素之和 刚好满足 sum / 2 即可,所以我们的 元素中的  价值 和 体积 都是 nums[] 元素值

代码详解如下:

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        vector<int>dp(200*100+10,0);   // 定义 dp 数组
        int sum = 0;    // 计算 (背包容量) 元素和
        for(int &i:nums) sum += i;
        if(sum % 2) return false;   // 如果元素和无法平分,返回 false
        else sum /= 2;
        
        // 开始遍历元素
        for(int &i:nums)
        {
            // 遍历(背包容量) 到达的平分元素和
            for(int j = sum ;j >= i;--j)
            {
                dp[j] = max(dp[j],dp[j - i] + i);
            }
        }
        
        return dp[sum] == sum;
    }
};

最后提交:

### 动态规划解决方案 分割子集问题是经典的 **动态规划 (Dynamic Programming)** **背包问题** 的变体。以下是基于动态规划的 Python 实现方法。 #### 算法思路 该问题可以通过转化为一个 0/1 背包问题来解决。如果整个数组 `nums` 中所有元素之为奇数,则无法分成两个相等的部分;如果是偶数,目标是找到是否存在一个子集其总等于整体的一半 (`target = sum(nums) / 2`)。 定义状态转移方程如下: - 设 `dp[j]` 表示容量为 `j` 的背包能否被填满。 - 初始状态:`dp[0] = True` (表示当没有任何物品时,容量为 0 的背包是可以被满足的)。 - 对于每一个数字 `num`,更新状态: 如果当前背包容量 `j >= num` 且之前的状态允许填充到容量 `j-num`,则可以将此数字加入背包中,即 `dp[j] |= dp[j - num]`[^1]。 最终检查 `dp[target]` 是否为真即可得出结论。 #### Python 实现代码 ```python def canPartition(nums): total_sum = sum(nums) if total_sum % 2 != 0: return False target = total_sum // 2 n = len(nums) # 初始化 DP 数组 dp = [False] * (target + 1) dp[0] = True for i in range(n): # 遍历每个数字 for j in range(target, nums[i]-1, -1): # 倒序遍历防止重复计算 dp[j] = dp[j] or dp[j - nums[i]] return dp[target] # 测试用例 print(canPartition([1, 5, 11, 5])) # 输出: True print(canPartition([1, 2, 3, 5])) # 输出: False ``` 上述代码实现了动态规划的核心逻辑,通过测试验证了正确性[^4]。 --- ### 复杂度分析 - 时间复杂度:O(n × m),其中 `n` 是数组长度,`m` 是目标值 `target`。 - 空间复杂度:O(m),仅需一维数组存储中间结果。 这种方法利用了动态规划的思想,在合理的时间范围内解决了问题[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值