416. 分割等和子集
416 分割等和子集
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
每个数组中的元素不会超过 100
数组的大小不会超过 200
示例 1:
输入: [1, 5, 11, 5]
输出: true
解释: 数组可以分割成 [1, 5, 5] 和 [11].
示例 2:
输入: [1, 2, 3, 5]
输出: false
解释: 数组不能分割成两个元素和相等的子集.
思路
判断是否有等和子集,对数组求和,那么问题转化为,在数组是否有一个序列的和等于数组和的一半
问题变成了一个01背包问题;
利用动态规划来求解,普通解法是建立一个二维数组
dp[i][j] 表示从0到i之间是否存在一种方案使得和为j 初始是 0即false;
- 解决边界问题
dp[i][0]=true : 因为当和为0的时候,数组下标0到i之间存在一种方案使得 和为0 (什么元素都不选)
dp[0][nums[0]]=true : 因为当和为nums[0]的时候,选择nums[0]为方案
- 解决递推问题
if(j>=nums[i]) 那么nums[i] 可以不被选取,也可以被选取。只需要将两者情况取或(只要有一个为true 则dp[i][j]为true):
dp[i][j]=dp[i−1][j]|dp[i][j−nums[i]];
if(j<nums[i]) 那么该元素不被选取:
dp[i][j]=dp[i−1][j];
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n = nums.size();
if(n < 2) return false;
int sum = accumulate(nums.begin(),nums.end(),0);
int MaxNum = *max_element(nums.begin(),nums.end());
//判断sum是否为奇数,按位与 最后一位是0 则为偶数,为1 则为奇数
if(sum & 1) return false;
int target = sum/2; //转化为 0 1 背包问题,即判断数组中是否存在和为target 的序列
if(MaxNum > target) return false;
//定义动态规划数组 dp[i][j] 表示从0到i之间 有没有和为j的序列
vector<vector<int> > dp(n,vector<int> (target+1,0));
for(int i=0;i<n;i++)
{
dp[i][0] = true;
}
dp[0][nums[0]] = true;
for(int i =1;i<n;i++)
{
int num = nums[i];
for(int j=1;j<=target ;j++)
{
if(j>=num)
{
dp[i][j] = dp[i-1][j] | dp[i-1][j-num];
}
else
{
dp[i][j] = dp[i-1][j];
}
}
if(dp[i][target]) return true;
}
return dp[n-1][target];
}
};
优化空间
把dp二维数组优化为一维的,这是因为每一次状态转移,dp[i][j]的值只与上一行数组有关。
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n = nums.size();
if(n < 2) return false;
int sum = accumulate(nums.begin(),nums.end(),0);
int MaxNum = *max_element(nums.begin(),nums.end());
//判断sum是否为奇数,按位与 最后一位是0 则为偶数,为1 则为奇数
if(sum & 1) return false;
int target = sum/2; //转化为 0 1 背包问题,即判断数组中是否存在和为target 的序列
if(MaxNum > target) return false;
vector<int> dp(target+1,0);
dp[0] = true;
if(nums[0] <= target)
dp[nums[0]] = true;
for(int i=1;i<n;i++)
{
for(int j = target;nums[i] <= j; j--)
{
if(dp[target])
{
return true;
}
dp[j] = dp[j] | dp[j - nums[i]];
}
}
return dp[target];
}
};
链接
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-equal-subset-sum
分类:
LeetCode题解笔记
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 官方的 MCP C# SDK:csharp-sdk
· 一款 .NET 开源、功能强大的远程连接管理工具,支持 RDP、VNC、SSH 等多种主流协议!
· 提示词工程师自白:我如何用一个技巧解放自己的生产力
· 一文搞懂MCP协议与Function Call的区别
· 如何不购买域名在云服务器上搭建HTTPS服务