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

相关推荐
Jerry14 小时前
LeetCode 160. 相交链表
算法
认真的酒窝14 小时前
自己动手开发编译器(十一)语义分析
java·开发语言
Jerry14 小时前
LeetCode 19. 删除链表的倒数第 N 个结点
算法
金銀銅鐵14 小时前
费马小定理
python·数学·算法
wbs_scy15 小时前
Linux C++ 高并发编程:线程池全链路深度解析,从原理到手撕实现
java·开发语言
JAVA面经实录91715 小时前
Linux 常用命令完整知识体系
java·linux·开发语言·汇编
技术不好的崎鸣同学15 小时前
[ACTF2020 新生赛]Exec 思路及解法
算法·安全·web安全
Full Stack Developme17 小时前
Java LRU 与 LFU 算法及应用
java·开发语言·算法
Jerry18 小时前
LeetCode 707. 设计链表
算法