[LeetCode] 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] Partition Equal Subset Sum 相同子集和分割的更多相关文章
- [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 ——Partition Equal Subset Sum
Question Given a non-empty array containing only positive integers, find if the array can be partiti ...
- LeetCode—— Partition Equal Subset Sum
Question Given a non-empty array containing only positive integers, find if the array can be partiti ...
- LN : leetcode 416 Partition Equal Subset Sum
lc 416 Partition Equal Subset Sum 416 Partition Equal Subset Sum Given a non-empty array containing ...
- 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
Given a non-empty array containing only positive integers, find if the array can be partitioned into ...
- [Swift]LeetCode416. 分割等和子集 | Partition Equal Subset Sum
Given a non-empty array containing only positive integers, find if the array can be partitioned into ...
随机推荐
- 解决新版Android studio导入微信支付和支付宝官方Demo的问题
最近项目要用到支付宝支付和微信支付,本想使用第三方支付框架ping++或者BeeCloud的,但是由于他们的收费问题,让我望而却步,而且公司给了相应的公钥.私钥和APPID等,所以就用下开放平台的呗. ...
- 连接SQLServer时,因启用连接池导致孤立事务的原因分析和解决办法
本文出处:http://www.cnblogs.com/wy123/p/6110349.html 之前遇到过这么一种情况: 连接数据库的部分Session会出现不定时的阻塞,这种阻塞时长时短,有时候持 ...
- css预处理器sass使用教程(多图预警)
css预处理器赋予了css动态语言的特性,如变量.函数.运算.继承.嵌套等,有助于更好地组织管理样式文件,以及更高效地开发项目.css预处理器可以更方便的维护和管理css代码,让整个网页变得更加灵活可 ...
- html5语义化标签使用规范
Html5添加了很多语义化标签,一个典型的html5页面结构可以如下安排 一.使用案例 1. 头部——header和nav标签 header头部,body下的直接子元素header一般用于放页面的介绍 ...
- 【WCF】如何将WCF部署到远程服务器
一.前言 最近需要将自己写的WCF服务部署到远程服务器上,也就是公网上.宿主是IIS,在配置成功之前遇到了很多问题,问题如下: 1. WCF该怎么宿主在IIS上,为何会出现 400 Bad ...
- python之最强王者(6)——列表(List)
1.Python 列表(List) 序列是Python中最基本的数据结构.序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推. Python有6个序列的内置 ...
- linux的基本语法及一些设置
rm -r note.txt //delete网络配置进入 vi /etc/sysconfig/network-scripts/ifcfg-teh0修改配置DEVICE=eth0BOOTPROTO=d ...
- JQuery中$.ajax()方法参数详解
url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如put和 ...
- jquery css3问卷答题卡翻页动画效果
这个选项调查的特效以选项卡的形式,每答完一道题目自动切换到下一条,颇具特色.使用jQuery和CSS3,适合HTML5浏览器. 效果展示 http://hovertree.com/texiao/jqu ...
- ArcGIS Engine开发之地图浏览
地图的浏览功能包括缩放.移动.量测旋转等. 1.放大与缩小 无论是放大还是缩小,都是通过改变MapControl中当前视图的范围Extent属性来实现的,主要用到包络线(Envelope)类. 包络线 ...