【动态规划】【01背包】Leetcode 416. 分割等和子集

【动态规划】【01背包】Leetcode 416. 分割等和子集

---------------🎈🎈416. 分割等和子集 题目链接🎈🎈-------------------

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

示例 1:

输入:nums = [1,5,11,5]

输出:true

解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:

输入:nums = [1,2,3,5]

输出:false

解释:数组不能分割成两个元素和相等的子集

[😒: 我的代码实现============>](#😒: 我的代码实现============>)

动规五部曲

⭐️本题中每一个元素的数值既是重量,也是价值

✒️确定dp数组以及下标的含义

dp[j]表示 背包总容量(所能装的总重量)是j。放进物品后,背的最大重量为dp[j]

如果背包容量为target, dp[target]就是装满 背包之后的重量,所以 当 dp[target] == target 的时候,就返回true。

✒️确定递推公式

物品i的重量是nums[i],其价值也是nums[i]。

所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);

✒️dp数组初始化

dp[0] = 0

✒️确定遍历顺序

如果使用一维dp数组,先正序遍历物品,后逆序遍历背包

✒️举例推导dp数组

时间复杂度O(N)
空间复杂度O(N)

📘代码

java 复制代码
class Solution {
    public boolean canPartition(int[] nums) {
    	// 遍历求出总和
        int sum = 0;
        for(int num:nums){
            sum +=num;
        }
        if(sum %2 == 1){ //如果和是奇数 那就不能平分。直接没戏
            return false;
        }
		
		// 根据总和得到一半儿的数值,接下来就是希望dp[target] = target,就返回true
        int target = sum/2;
        int[] dp = new int[target+1];
        dp[0] = 0;

        //dp[j] 容量为j的背包能放的最大价值 (本题重量为元素的数值,价值也为元素的数值)
        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]);  // 物品 i 的重量是 nums[i],其价值也是 nums[i]
            }
        }
	
		// 如果dp[target] == target,那么就说明可以拆成两个相等的子集
        if(dp[target] == target){
            return true;
        }
        else{
            return false;
        }
    }
}          
相关推荐
Hui Baby30 分钟前
springAi+MCP三种
java
hsjcjh33 分钟前
【MySQL】C# 连接MySQL
java
敖正炀33 分钟前
LinkedBlockingDeque详解
java
wangyadong31734 分钟前
datagrip 链接mysql 报错
java
untE EADO40 分钟前
Tomcat的server.xml配置详解
xml·java·tomcat
ictI CABL1 小时前
Tomcat 乱码问题彻底解决
java·tomcat
敖正炀1 小时前
DelayQueue 详解
java
敖正炀1 小时前
PriorityBlockingQueue 详解
java
shark22222221 小时前
Spring 的三种注入方式?
java·数据库·spring
workflower1 小时前
机器人应用-楼宇室内巡逻
大数据·人工智能·算法·microsoft·机器人·动态规划·享元模式