这道题还可以用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<5001> bits(1);
int sum = accumulate(nums.begin(), nums.end(), 0);
for (int num : nums) bits |= bits << num;
return (sum % 2 == 0) && bits[sum >> 1];
}
};
他举的例子的确是没问题,但是为什么呢?左进1位×2,右进1位/2,那么为什么可以通过左进num位,同时保证对应的数字位置为1(这个还好理解点)同时所有可能的和也为1呢?