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 背包判断是否恰好装满。

相关推荐
M-Robots echo5 小时前
轻量化裁剪方案解析:M-Robots 模块化构建,适配高低端各类机器人硬件平台
java·机器人·ros·开源社区·atomgit·m-robots
不可求~5 小时前
多模型路由怎么落地:把任务分流写进项目的最小实现
java·前端·数据库
数模竞赛Paid answer5 小时前
2026年中青杯数学建模A题数学建模论文智能评估系统与多智能体优化方法求解全过程论文及程序
算法·数学建模·中青杯
银-豆豆5 小时前
数据结构与算法-动态规划、回溯与贪心
算法·动态规划
mldong6 小时前
用 DDD 设计工作流引擎:聚合根与充血模型
java·架构
mqiqe7 小时前
AgentScope Java Harness:4. 双层记忆系统 让 Agent 拥有真正的“长期大脑“
java·开发语言
伍一517 小时前
03-文件管理模块-一个看似简单的模块藏着多少细节
java·ruoyi·若依
想吃火锅10057 小时前
【leetcode】200. 岛屿数量
算法·leetcode·职场和发展
gugucoding7 小时前
46. 【Java】JUC并发工具:让并发更简单
java·开发语言
Nil2088 小时前
leetcode 54螺旋矩阵
算法·leetcode·矩阵