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/

https://leetcode.com/problems/partition-equal-subset-sum/discuss/90592/01-knapsack-detailed-explanation

https://leetcode.com/problems/partition-equal-subset-sum/discuss/90590/Simple-C++-4-line-solution-using-a-bitset

https://leetcode.com/problems/partition-equal-subset-sum/discuss/90588/Concise-C++-Solution-summary-with-DFS-DP-BIT

https://leetcode.com/problems/partition-equal-subset-sum/discuss/90627/Java-Solution-similar-to-backpack-problem-Easy-to-understand

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 416. Partition Equal Subset Sum 相同子集和分割的更多相关文章

  1. LN : leetcode 416 Partition Equal Subset Sum

    lc 416 Partition Equal Subset Sum 416 Partition Equal Subset Sum Given a non-empty array containing ...

  2. [leetcode]416. Partition Equal Subset Sum分割数组的和相同子集

    Given a non-empty array containing only positive integers, find if the array can be partitioned into ...

  3. [LeetCode] Partition Equal Subset Sum 相同子集和分割

    Given a non-empty array containing only positive integers, find if the array can be partitioned into ...

  4. Leetcode 416. Partition Equal Subset Sum

    Given a non-empty array containing only positive integers, find if the array can be partitioned into ...

  5. 【LeetCode】416. Partition Equal Subset Sum 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS 动态规划 日期 题目地址:https://l ...

  6. 【leetcode】416. Partition Equal Subset Sum

    题目如下: 解题思路:对于这种判断是否的题目,首先看看动态规划能不能解决.本题可以看成是从nums中任选i个元素,判断其和是否为sum(nums)/2,很显然从nums中任选i个元素的和的取值范围是[ ...

  7. 416. Partition Equal Subset Sum

    题目: Given a non-empty array containing only positive integers, find if the array can be partitioned ...

  8. 416 Partition Equal Subset Sum 分割相同子集和

    详见:https://leetcode.com/problems/partition-equal-subset-sum/description/ C++: class Solution { publi ...

  9. LC 416. Partition Equal Subset Sum

    题目 Given a non-empty array containing only positive integers, find if the array can be partitioned i ...

随机推荐

  1. LeetCode 133:克隆图 Clone Graph

    题目: 给定无向连通图中一个节点的引用,返回该图的深拷贝(克隆).图中的每个节点都包含它的值 val(Int) 和其邻居的列表(list[Node]). Given a reference of a ...

  2. .net core 发布到iis问题 HTTP Error 500.30 - ANCM In-Process Start Failure

    1. 没有在Program里配置IIS webBuilder.UseIIS(); 2. StartupProduction 里AutoFac容器注入错误和新版的CORS中间件已经阻止使用允许任意Ori ...

  3. js函数定义及一些说明

    1.javascript定义函数的三种方法一.function语句//这个方法比较常用function fn(){ alert("这是使用function语句进行函数定义");}f ...

  4. windows小乌龟和git使用

    一.安装git for windows 首先下载git for windows客户端http://msysgit.github.io/ 安装过程没什么特别的,不停next就ok了     图太多就不继 ...

  5. python数据分析&挖掘,机器学习环境配置

    目录 一.什么是数据分析 1.这里引用网上的定义: 2.数据分析发展与组成 3.特点 二.python数据分析环境及各类常用分析包配置 1.处理的数据类型 2.为什么选择python 三.python ...

  6. Python【day 10】函数进阶-动态函数

    形参小结 1.位置参数2.默认值参数3.动态参数 1.*args 位置参数的动态传参. 系统会自动的把所有的位置参数聚合成元组 2.**kwargs 关键字参数的动态传参. 系统会自动的把所有的关键字 ...

  7. Qt程序app添加图标复制到其它电脑后不显示的解决方法

    原因: 主是要因为Qt显示图标需要依赖一些库来进行转换,而复制到其它电脑后不显示,是没有复制相应的库所致,所以把相应库复制过去就行了. 复制Qt的plugins目录下的imageformats文件到程 ...

  8. 使用Composer安装阿里云短信失败

    安装步骤 请参考以下步骤,使用Composer安装依赖. 如果在您的系统上全局安装Composer,您可以在项目目录中运行以下内容,将 Alibaba Cloud Client for PHP 添加为 ...

  9. 基于hashlib下的文件校验

    hashlib不仅可以对密码进行加密也可以对文件内容进行校验,传统的小文件校验通过人为校验是不现实的,如果摸个文件里面的内容多出一个空格的话那么哦是根本就不知道的因此我们需要一个可以校验文件的方法,而 ...

  10. 洛谷 P5564: [Celeste-B]Say Goodbye

    题目传送门:洛谷 P5564. 题意简述: 有 \(n\) 个点,染 \(m\) 种颜色,第 \(i\) 种颜色染恰好 \(cnt_i\) 个节点,满足 \(cnt_1+cnt_2+\cdots+cn ...