698. Partition to K Equal Sum Subsets
Given an array of integers nums and a positive integer k, find whether it’s possible to divide this array into k non-empty subsets whose sums are all equal.
Example 1:
Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
Output: True
Explanation: It's possible to divide it into 4 subsets (5), (1, 4), (2,3), (2,3) with equal sums.
Note:
- 1 <= k <= len(nums) <= 16.
- 0 < nums[i] < 10000.
Analyze:
对于动态规划的问题,我们首先需要找到它的状态转移方程。
分析题干,可以很容易的知道,每组都需要满足的和就是集合内所有元素的和再除以组数,得到每个集合的目标值。
然后寻找状态转移的式子,当前i个数字能够满足所有分组的和都相等,那么前i-1个数字中,在目标状态的集合中减去一个数字ai也能够满足条件,即:
b(i, c1, c2, ..., ck) = b(i-1, c1-ai, c2, ..., ck) ∪
b(i-1, c1, c2-ai, ..., ck) ∪
...∪
b(i-1, c1, c2, ..., ck-ai)
Code:
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
bool canPartitionKSubsets(vector<int>& nums, int k) {
int sum = 0;
for (int num : nums) sum += num;
// 若求得的和不能整数均分或小于0的话就不满足要求
if (k <= 0 || sum % k != 0) return false;
// 判断是否可以访问
vector<int> visited(nums.size(), 0);
return canPartition(nums, visited, 0, k, 0, 0, sum / k);
}
/*
* @params nums 表示输入的一组数字
* @params visited 表示可以使用的数字
* @params start_index 表示开始的序号,即前i个能不能分成k个组
* @params k 输入的k组
* @params cur_sum 表示目前的和
* @params cur_num 表示目前集合中的数字
* @params target 表示目标和
*/
bool canPartition(vector<int>& nums, vector<int>& visited, int start_index, int k, int cur_sum, int cur_num, int target) {
// 若只需要分一组,那么绝对能够将集合里的数分成一组
if (k == 1)return true;
// 若一个集合的和达到目标值,且集合不为空集,则判断剩下的数能不能分成k-1个集合
if (cur_sum == target && cur_num > 0) return canPartition(nums, visited, 0, k - 1, 0, 0, target);
// 从未被选择的数字开始算
for (int i = start_index; i < nums.size(); i++) {
if (!visited[i]) {
visited[i] = 1;
if (canPartition(nums, visited, i + 1, k, cur_sum + nums[i], cur_num++, target))
return true;
visited[i] = 0;
}
}
return false;
}
};

914

被折叠的 条评论
为什么被折叠?



