package leecode;
/**
* 698. 划分为k个相等的子集
* 给定一个整数数组 nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。
*
*
* @author Tang
* @date 2021/12/10
*/
public class CanPartitionKSubsets {
int[] nums;
int[] bucket;
int target;
/**
* 通过回溯 实现穷举
* 穷举直到满足所有总和相等 或者失败
*
* @param nums
* @param k
* @return
*/
public boolean canPartitionKSubsets(int[] nums, int k) {
this.nums = nums;
//创建k个桶
this.bucket = new int[k];
//创建每个桶的目标值
//因为nums平均分给k个桶
for (int num : nums) {
target+=num;
}
target = target / k;
return track(0);
}
/**
* 挨个元素判断,
* 递归桶,判断当前元素该不该入桶
*
* @param index 当前玩第几个元素
*/
private boolean track(int index) {
//元素到头了
if(index == nums.length) {
int temp = bucket[0];
for (int b : bucket) {
//只要有一个元素不和第一个元素相同就说明不全相等
if (b != temp) {
return false;
}
}
return true;
}
//循环桶 判断当前元素该不该加入这个桶
for(int i = 0; i < bucket.length; i++) {
//剪枝 超过桶正常大小的不要再递归算了
if(bucket[i] > target) {
continue;
}
//递归前做出选择
//入桶
bucket[i] = bucket[i] + nums[index];
//执行递归 去玩下一个元素
boolean track = track(index + 1);
if(track) {
//减少剩余的操作
return true;
}
//递归后撤销选择
bucket[i] = bucket[i] - nums[index];
}
return false;
}
public static void main(String[] args) {
}
}