LeetCode 416:分割等和子集 —— (0-1背包)

LeetCode 416:分割等和子集 ------ (0-1背包)

🔗 题目链接

👉 https://leetcode.cn/problems/partition-equal-subset-sum/


📖 内容概要

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

✅ 使用 0/1 背包思想

✅ 一维 DP 优化

✅ 时间复杂度 O(n × sum)

✅ 空间复杂度 O(sum)


💡 解题思路

一、问题转化(最关键一步)

能否从数组中选出若干个数,使其和等于 sum / 2

如果能,那么剩下的数之和也一定是 sum / 2。


二、可行性剪枝

  • 如果数组总和是奇数:

    java 复制代码
    if (sum % 2 == 1) return false;
  • 不可能平分


三、0/1 背包建模

概念 对应
物品 数组中的每个数
重量 数值大小nums[i]
价值 数值大小 nums[i]
背包容量 target = sum / 2

✅ 判断是否能恰好装满容量为 target 的背包


四、DP 定义

java 复制代码
dp[j] = 容量为 j 的背包,能装的最大价值

目标:

java 复制代码
dp[target] == target

五、状态转移方程

java 复制代码
dp[j] = max(
    dp[j],                     // 不选当前数
    dp[j - nums[i]] + nums[i]  // 选当前数
)

六、遍历顺序(非常重要)

java 复制代码
for (int i = 0; i < n; i++) {
    for (int j = target; j >= nums[i]; j--) {
        dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
    }
}

✅ j 必须从大到小

  • 防止同一物品被重复使用
  • 保证是 0/1 背包

✅ AC 代码(Java)

java 复制代码
class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }

        // 奇数不可能平分
        if (sum % 2 == 1) return false;

        int target = sum / 2;
        int[] dp = new int[20001]; // dp[j]: 容量为 j 的最大价值和

        // 0/1 背包
        for (int i = 0; i < nums.length; i++) {
            for (int j = target; j >= nums[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
            }
        }

        return dp[target] == target;
    }
}

⏱️ 复杂度分析

指标 复杂度
时间复杂度 O(n × sum)
空间复杂度 O(sum)

⚠️ 时间复杂度不是 O(n²),而是由数值总和决定


✅ 核心总结一句话

把"能否平分数组"转化为"是否存在子集和为 sum/2",再用 0/1 背包判断是否恰好装满。

相关推荐
code2cat几秒前
【随笔】MCP资源更新订阅:通知到达以后,Agent怎样刷新旧资料
java·后端·开发工具·ai agent·mcp
mmmmath_323 分钟前
LeetCode.020.有效的括号
数据结构·算法·leetcode
Doubbbbbbble云43 分钟前
算法优化中的数学建模与理论界限分析4
算法·数学建模
垆边人似月.1 小时前
华为机考题:字符个数统计
数据结构·算法·华为
一只旭宝1 小时前
C++ 后端开发面试题整理
java·c++·面试
sunshine22 girl1 小时前
Java学习五 面向对象高级5 内部类3-静态内部类和局部内部类(了解)
java·学习
en.en..1 小时前
Linux 进程退出exit(函数)
java·开发语言·算法
李游Leo1 小时前
HarmonyOS 7 TaskPool + Node-API + zstd:Native 批量压缩任务的主线程隔离、进度回传与资源收口【鸿蒙心迹】
java·华为·harmonyos
Light Gao1 小时前
Encoder 与 Decoder 详解:从 Embedding 到 Seq2Seq 的完整数据流
java·开发语言·embedding
All for pursuit.1 小时前
【回溯-2】22.括号生成
数据结构·c++·算法·leetcode