87.分割成两个等和数组 leetcode416

给你一个 只包含正整数非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

示例 1:

复制代码
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:

复制代码
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。
cpp 复制代码
bool canPartition(int* nums, int numsSize) {
    int sum = 0;
    for(int i=0;i<numsSize;i++){
        sum+=nums[i];
    }
    int target = sum/2;
    if(sum%2!=0)
        return false;
    bool* dp = (bool*)malloc(sizeof(bool)*(target+1));//覆盖0->target所有情况
    //dp[i]:可以从数组中取出元素和 = i吗?
    dp[0] = true;
    for(int i=1;i<=target;i++){
        dp[i] = false;
    }
    //dp[target]表示能从数组中选出元素和为target
    // bool choose = dp[target-nums[i]];//物品遍历到nums[i]且选择这个物品,那dp[target]取决于dp[target-nums[i]]了
    //bool notchoose = dp[target]//不选nums[i]

    for(int i=0;i<numsSize;i++){
        for(int j=target;j>=nums[i];j--){
            dp[j] = dp[j] || dp[j-nums[i]]; 
        }
    }
    return dp[target];
    
}

初始状态(处理任何元素前)

dp 数组长度 = 12(0~11),初始值:dp = [true, false, false, false, false, false, false, false, false, false, false, false](只有 dp [0]=true,其余都是 false)


第一轮:处理第一个元素 current_num=1

遍历 j 的顺序:j=11 → 10 → 9 → ... → 2 → 1(倒序)逐个处理每个 j,记录 dp 变化:

表格

j 值 not_choose(不选 1) choose(选 1,即 dp [j-1]) dp [j] 更新后 关键说明
11 false dp[10]=false false 无变化
10 false dp[9]=false false 无变化
9 false dp[8]=false false 无变化
8 false dp[7]=false false 无变化
7 false dp[6]=false false 无变化
6 false dp[5]=false false 无变化
5 false dp[4]=false false 无变化
4 false dp[3]=false false 无变化
3 false dp[2]=false false 无变化
2 false dp[1]=false false 无变化
1 false dp[0]=true true 唯一更新

本轮结束后 dp 数组dp = [true, true, false, false, false, false, false, false, false, false, false, false]→ 此时 dp [11] 还是 false!因为只处理了 1,凑不出 11。


第二轮:处理第二个元素 current_num=5

遍历 j 的顺序:j=11 → 10 → ... → 5(j≥5)逐个处理:

表格

j 值 not_choose(不选 5) choose(选 5,即 dp [j-5]) dp [j] 更新后 关键说明
11 false dp[6]=false false 无变化
10 false dp[5]=false false 无变化
9 false dp[4]=false false 无变化
8 false dp[3]=false false 无变化
7 false dp[2]=false false 无变化
6 false dp[1]=true true 选 5+1=6
5 false dp[0]=true true 选 5=5

本轮结束后 dp 数组dp = [true, true, false, false, false, true, true, false, false, false, false, false]→ dp [11] 依然 false!但 dp [5]、dp [6] 变成 true(为后续铺路)。


第三轮:处理第三个元素 current_num=11

遍历 j 的顺序:j=11(只有 j≥11,所以只遍历 j=11)处理:

表格

j 值 not_choose(不选 11) choose(选 11,即 dp [j-11]) dp [j] 更新后 关键说明
11 false dp[0]=true true 选 11=11

本轮结束后 dp 数组dp = [true, true, false, false, false, true, true, false, false, false, false, true]→ 终于!dp [11] 变成 true 了。

相关推荐
dazzle7 小时前
机器学习算法原理与实践-入门(十一):基于PyTorch的房价预测实战
pytorch·算法·机器学习
袋鼠云数栈14 小时前
集团数字化统战实战:统一数据门户与全业态监管体系构建
大数据·数据结构·人工智能·多模态
小月球~15 小时前
天梯赛 · 并查集
数据结构·算法
仍然.15 小时前
算法题目---模拟
java·javascript·算法
6Hzlia16 小时前
【Hot 100 刷题计划】 LeetCode 118. 杨辉三角 | C++ 动态规划题解
c++·leetcode·动态规划
三道渊16 小时前
C语言:文件I/O
c语言·开发语言·数据结构·c++
kali-Myon17 小时前
CTFshow-Pwn142-Off-by-One(堆块重叠)
c语言·数据结构·安全·gdb·pwn·ctf·
潇冉沐晴17 小时前
DP——背包DP
算法·背包dp
GIOTTO情17 小时前
2026 世界互联网大会亚太峰会|AI 时代媒介投放的技术实战与算法优化
人工智能·算法
逆境不可逃18 小时前
LeetCode 热题 100 之 543. 二叉树的直径 102. 二叉树的层序遍历 108. 将有序数组转换为二叉搜索树 98. 验证二叉搜索树
算法·leetcode·职场和发展