[LeetCode] 416. Partition Equal Subset Sum 相同子集和分割
Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
Both the array size and each of the array element will not exceed 100.
Example 1:
Input: [1, 5, 11, 5] Output: true Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5] Output: false Explanation: The array cannot be partitioned into equal sum subsets.
这道题给了我们一个数组,问这个数组能不能分成两个非空子集合,使得两个子集合的元素之和相同。那么想,原数组所有数字和一定是偶数,不然根本无法拆成两个和相同的子集合,只需要算出原数组的数字之和,然后除以2,就是 target,那么问题就转换为能不能找到一个非空子集合,使得其数字之和为 target。开始博主想的是遍历所有子集合,算和,但是这种方法无法通过 OJ 的大数据集合。于是乎,动态规划 Dynamic Programming 就是不二之选。定义一个一维的 dp 数组,其中 dp[i] 表示原数组是否可以取出若干个数字,其和为i。那么最后只需要返回 dp[target] 就行了。初始化 dp[0] 为 true,由于题目中限制了所有数字为正数,就不用担心会出现和为0或者负数的情况。关键问题就是要找出状态转移方程了,需要遍历原数组中的数字,对于遍历到的每个数字 nums[i],需要更新 dp 数组,既然最终目标是想知道 dp[target] 的 boolean 值,就要想办法用数组中的数字去凑出 target,因为都是正数,所以只会越加越大,加上 nums[i] 就有可能会组成区间 [nums[i], target] 中的某个值,那么对于这个区间中的任意一个数字j,如果 dp[j - nums[i]] 为 true 的话,说明现在已经可以组成 j-nums[i] 这个数字了,再加上 nums[i],就可以组成数字j了,那么 dp[j] 就一定为 true。如果之前 dp[j] 已经为 true 了,当然还要保持 true,所以还要 ‘或’ 上自身,于是状态转移方程如下:
dp[j] = dp[j] || dp[j - nums[i]] (nums[i] <= j <= target)
有了状态转移方程,就可以写出代码了,这里需要特别注意的是,第二个 for 循环一定要从 target 遍历到 nums[i],而不能反过来,想想为什么呢?因为如果从 nums[i] 遍历到 target 的话,假如 nums[i]=1 的话,那么 [1, target] 中所有的 dp 值都是 true,因为 dp[0] 是 true,dp[1] 会或上 dp[0],为 true,dp[2] 会或上 dp[1],为 true,依此类推,完全使的 dp 数组失效了,参见代码如下:
解法一:
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = accumulate(nums.begin(), nums.end(), ), target = sum >> ;
if (sum & ) return false;
vector<bool> dp(target + , false);
dp[] = true;
for (int num : nums) {
for (int i = target; i >= num; --i) {
dp[i] = dp[i] || dp[i - num];
}
}
return dp[target];
}
};
这道题还可以用 bitset 来做,感觉也十分的巧妙,bisets 的大小设为 5001,为啥呢,因为题目中说了数组的长度和每个数字的大小都不会超过 100,那么最大的和为 10000,那么一半就是 5000,前面再加上个0,就是 5001 了。初始化把最低位赋值为1,算出数组之和,然后遍历数字,对于遍历到的数字 num,把 bits 向左平移 num 位,然后再或上原来的 bits,这样所有的可能出现的和位置上都为1。举个例子来说吧,比如对于数组 [2,3] 来说,初始化 bits 为1,然后对于数字2,bits 变为 101,可以看出来 bits[2] 标记为了1,然后遍历到3,bits 变为了 101101,看到 bits[5],bits[3],bits[2] 都分别为1了,正好代表了可能的和 2,3,5,这样遍历完整个数组后,去看 bits[sum >> 1] 是否为1即可,参见代码如下:
解法二:
class Solution {
public:
bool canPartition(vector<int>& nums) {
bitset<> bits();
int sum = accumulate(nums.begin(), nums.end(), );
for (int num : nums) bits |= bits << num;
return (sum % == ) && bits[sum >> ];
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/416
类似题目:
Partition to K Equal Sum Subset
参考资料:
https://leetcode.com/problems/partition-equal-subset-sum/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 416. Partition Equal Subset Sum 相同子集和分割的更多相关文章
- LN : leetcode 416 Partition Equal Subset Sum
lc 416 Partition Equal Subset Sum 416 Partition Equal Subset Sum Given a non-empty array containing ...
- [leetcode]416. Partition Equal Subset Sum分割数组的和相同子集
Given a non-empty array containing only positive integers, find if the array can be partitioned into ...
- [LeetCode] Partition Equal Subset Sum 相同子集和分割
Given a non-empty array containing only positive integers, find if the array can be partitioned into ...
- Leetcode 416. Partition Equal Subset Sum
Given a non-empty array containing only positive integers, find if the array can be partitioned into ...
- 【LeetCode】416. Partition Equal Subset Sum 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS 动态规划 日期 题目地址:https://l ...
- 【leetcode】416. Partition Equal Subset Sum
题目如下: 解题思路:对于这种判断是否的题目,首先看看动态规划能不能解决.本题可以看成是从nums中任选i个元素,判断其和是否为sum(nums)/2,很显然从nums中任选i个元素的和的取值范围是[ ...
- 416. Partition Equal Subset Sum
题目: Given a non-empty array containing only positive integers, find if the array can be partitioned ...
- 416 Partition Equal Subset Sum 分割相同子集和
详见:https://leetcode.com/problems/partition-equal-subset-sum/description/ C++: class Solution { publi ...
- LC 416. Partition Equal Subset Sum
题目 Given a non-empty array containing only positive integers, find if the array can be partitioned i ...
随机推荐
- 此贴告诉你:为啥shell脚本人,不建议学python
py很强大,我承认.但在运维方面,py不但不强大,还有硬伤.正因为有下述硬伤,所以我们运维,还是用shell多,用py极少.我看到用shell的人很多,你建议人用python,人说py是很好,但下一秒 ...
- 【Zabbix】zabora监控Oracle数据库
zabora监控Oracle数据库 它作为一个开源项目,通过shell脚本有效的监控Oracle基础指标.本文档旨在通过实战,在Zabbix 3.0版本之下,监控生产环境下的多台Oracle数据库. ...
- 在Angular4中使用ng2-baidu-map详解
一.引言 之前在Angular4使用过百度地图,记录一下踩过的坑 二.实现 1.安装 npm install angular2-baidu-map 2.在app.module.ts配置 ak key在 ...
- sess文件编译输出css的四种方式以及使用
sess文件输出css有下面四种方式: :nested(嵌套) :compact(紧凑) :expanded(展开) :compressed(压缩) 如何使用: sass --watch style. ...
- Struts2 OGNL表达式、ValueStack
OGNL简介 OGNL,即Object-Graph Navigation Language,对象视图导航语言,是一种数据访问语言,比EL表达式更加强大: EL只能从11个内置对象中取值,且只能获取属性 ...
- Mac下多版本pip共存
Mac下多版本pip共存 来自于官方的解释, pip是python包管理工具, 该工具提供了对python包的查找, 下载, 安装, 卸载等功能python第三方工具包多数依赖于pip进行安装, 如 ...
- 如何在浏览器中运行 VS Code?
摘要: WEB IDE新时代! 作者:SHUHARI 的博客 原文:有趣的项目 - 在浏览器中运行 Visual Studio Code Fundebug按照原文要求转载,版权归原作者所有. 众所周知 ...
- c# list集合简单快捷取随机
C#怎么在list集合中随机取出一个值: 首先我们取出这个List列表 然后生成随机数 最后通过这个随机数当作索引实现 var list = studentlist.OrderBy(a => a ...
- SQL server 无法更新标识列
若是数据库设置了自增长字段,相应的Model也要做标记,否则修改数据的时候会提示无法更新条目 /// <summary> /// 自增长ID /// </summary> [D ...
- 使用类似GeoJson的数据生成物体(建筑等)的功能逻辑
GeoJson作为一种模型传输格式, 用的最多的就是地图里面的各种简单模型了, 比如下图中很贴切的俄罗斯方块楼: 它的格式大概就是下面这样: { "type": "Fea ...