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

相关推荐
猫头虎9 小时前
什么是ZCode for GLM-5.2?
开发语言·人工智能·python·科技·算法·ai编程·ai写作
Ivanqhz9 小时前
Rust Lazy浅析
java·javascript·rust
长不胖的路人甲9 小时前
什么是赫夫曼树(哈夫曼树 / Huffman Tree)
python·算法·霍夫曼树
bksczm10 小时前
Linux之日志和线程池、内存池
java·开发语言
笨蛋不要掉眼泪10 小时前
Java虚拟机:对象复活、引用强度与Stop-The-World
java·开发语言·jvm
Warren2Lynch10 小时前
掌握 UML 构造型、标记定义与标记值:面向领域特定建模的 UML 扩展全面指南
大数据·算法·uml
凤山老林10 小时前
SpringBoot实战:构建优雅的全局异常处理机制
java·springboot·异常处理
1570925113411 小时前
【无标题】
开发语言·python·算法
小Ti客栈11 小时前
Spring Boot 整合 Swagger2 和 Knife4j实现接口文档与可视化调试
java·spring boot·后端
梅头脑11 小时前
ThreadLocalMap里几十万个死Entry——排查了半天OOM,根因就一行finally没写
java