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.
给出一个数组,要分成k个非空子数组,使每个子数组的和都相等。
思路:
每个小组可以是不连续的,考虑DFS遍历
首先求数组的和sum,因为每个小组的和相等,所以每个小组的和应该是sum/k。当sum/k不是整数时,直接返回false。
当一个小组满足和为sum/k时,到下一小组,k减去1,同时和清零。
DFS的流程:
dfs(...):
边界条件
for i = start to end
if(visited[i]) continue
visited[i] = true
dfs(...)
visited[i] = false
这里边界条件就是和到了sum/k时,就要继续寻找下一小组,小组数还剩下0时,就返回true
所以要传入现在计算的和,目标和sum/k,还有剩下的小组数k
为了方便剪枝,先把数组排序,从大到小遍历,这样当前和超过sum/k,就不需要再迭代下去了。
但是这个剪枝的判断不要写在循环里,因为在循环里一旦返回false,整个循环就结束了,后面小的也不会再遍历了。所以也放在边界条件里面。
class Solution {
boolean[] visited;
int n = 0;
public boolean canPartitionKSubsets(int[] nums, int k) {
n = nums.length;
int sum = 0;
for(int i = 0; i < n; i ++) {
sum += nums[i];
}
if(sum % k != 0) {
return false;
}
visited = new boolean[n];
Arrays.sort(nums);
return dfs(nums, k, n-1, sum/k, 0);
}
boolean dfs(int[] nums, int k, int start, int target, int cur) {
if(k == 0) {
return true;
}
if(cur > target) {
return false;
}
if(cur == target) {
return dfs(nums, k-1, n-1, target, 0);
}
for(int i = start; i >= 0; i --) {
if(visited[i]) continue;
visited[i] = true;
if(dfs(nums, k, i-1, target, nums[i]+cur)) return true;
visited[i] = false;
}
return false;
}
}
该博客探讨了一个编程问题,即给定一个整数数组和一个正整数k,判断是否能将数组分成k个和相等的非空子集。文中提到,可以通过深度优先搜索(DFS)策略来解决此问题,首先计算数组总和,如果总和不能被k整除,则直接返回false。接着,对数组进行排序并从大到小遍历,以优化剪枝过程。在DFS过程中,当当前和等于目标和时,进入下一个子集,并递归地进行DFS。博客提供了详细的代码实现,包括关键的剪枝策略和边界条件处理。
1195

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



