问题描述
给定一个整数数组 nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。
示例 1:
输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
输出: True
说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。
注意:
1 <= k <= len(nums) <= 16
0 < nums[i] < 10000
解决思路
1、求出nums所有数字的总和,除以k求出平均数,如果不能整除,直接返回false
2、对nums排序
3、创建k个桶,每个桶的初始值都是平均数
4、从nums的最后一个数字开始,等于桶里的值或者小于并且减去之后的值大于nums中最小的一个
代码
import java.util.Arrays;
class Solution {
public static void main(String[] args) {
Solution solution=new Solution();
solution.canPartitionKSubsets(new int[]{4, 3, 2, 3, 5, 2,1},4);
}
public boolean canPartitionKSubsets(int[] nums, int k) {
int sum=0;
for(int i:nums){
sum+=i;
}
if(sum%k!=0){
return false;
}
int avg=sum/k;//平均k个
//对nums排序
Arrays.sort(nums);
//创建k个桶
int[] arr=new int[k];
//初始值都为avg,当所有桶的数字都能减为0,说明可以分完
Arrays.fill(arr,avg);
return fill(nums,nums.length-1,arr,k);
}
public boolean fill(int[] nums,int cur,int[] arr,int k){
if(cur<0){
return true;
}
for(int i=0;i<k;i++){
//满足条件就减去相应的数
if(arr[i]==nums[cur]||(cur>0&&arr[i]-nums[cur]>=nums[0])){
arr[i]-=nums[cur];
if(fill(nums,cur-1,arr,k)){
//k个桶都减完了,返回true
return true;
}
arr[i]+=nums[cur];
}
}
return false;
}
}