对于本题,首先去排除不可能的情况。
如果数组的和不能整除k,则不满足要求。
如果有某个元素大于sum/k,则不满足要求。
排除完特殊情况就该进入正题,创建一个bucket数组记录每个子数组的和。
再整个过程中需要给bucket[i]加上num[m],如果不合适去掉,所以可以想到回溯算法。
选择参数index,如果index==nums.size 那么就结束。
如果bucket[i]+num[m]>sum/k,则不符合要求,然后退出num[m]再进一步回溯。
class Solution {
public:
bool canPartitionKSubsets(vector<int>& nums, int k) {
if(k > nums.size()) return false;
int sum = accumulate(nums.begin(), nums.end(), 0);
if(sum % k != 0) return false;
sort(nums.rbegin(), nums.rend());
bucket.resize(k);
int target = sum/k;
return backtrack(nums, 0, target);
}
private:
// 记录每个子集中数字之和
vector<int> bucket;
bool backtrack(vector<int> &nums, int index, int target){
if(index == nums.size()){
return true;
}
for(int i = 0; i < bucket.size(); i++){
if(bucket[i] + nums[index] > target){
continue;
}
if(i > 0 && bucket[i] == bucket[i-1]){
continue;
}
bucket[i] += nums[index];
if(backtrack(nums, index + 1, target)){
return true;
}
bucket[i] -= nums[index];
}
return false;
}
};