题目描述
给定一个整数数组 nums
和一个正整数 k
,找出是否有可能把这个数组分成 k
个非空子集,其总和都相等。
示例 1:
输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 输出: True 说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。
示例 2:
输入: nums = [1,2,3,4], k = 3 输出: false
提示:
1 <= k <= len(nums) <= 16
0 < nums[i] < 10000
- 每个元素的频率在
[1,4]
范围内
AC代码
class Solution {
public:
bool dfs(vector<int>& nums, int k, int i, int m, int cell[]) {
// 结束条件
if (i == nums.size()) return true;
//继续搜索
for (int i1 = 0; i1 < k; i1++) {
//剪枝
if (cell[i1] + nums[i] > m) continue;
if (i1 > 0 && cell[i1 - 1] == cell[i1]) continue;
cell[i1] += nums[i];
if (dfs(nums, k, i + 1, m, cell)) return true; //深搜成功
//深搜失败回溯后减去值,继续for循环
cell[i1] -= nums[i];
}
return false;
}
bool canPartitionKSubsets(vector<int>& nums, int k) {
//不可能的情况:总和除以k并非整数,或最大值大于每个子集的和
int n = nums.size();
int sum = 0;
int cell[k];
memset(cell, 0, sizeof(cell));
for (int n1 = 0; n1 < n; n1++) {
sum += nums[n1];
} //使用库函数求数组和:int sum = accumulate(nums.begin(), nums.end(), 0);
if (sum % k) return false;
sort(nums.begin(), nums.end());
int m = sum / k;
if (nums.back() > m) return false;
//深搜回溯
return dfs(nums, k, 0, m, cell);
}
};