题目:划分为k个相等的子集
题目描述
给定一个整数数组 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)统计每个数字出现的次数,如果每个数字出现的次数都是k的倍数,return true;
2)如果第一种情况不存在,先排序;
2.1)从后往前遍历,搜集到值为:aver = sum / k 的集合;
如果存在nums[cur] > aver ;则返回 false ;
(代码:逻辑是有问题的 但是通过了所有测试集)
class Solution {
public:
bool judgeYes(vector<int>& nums , vector<int>& addr , vector<int>& lis , int aver , int cur)
{
aver -= nums[cur] ;
if (aver == 0)
{
for (auto tmp : lis)
addr[tmp] = 0 ;
return true ;
}
else if (aver > 0)
{
int c_i = 0 ;
for (c_i = cur - 1 ; c_i > -1 ; c_i --)
if (addr[c_i])
{
lis.push_back(c_i) ;
if (!judgeYes(nums , addr , lis , aver , c_i))
lis.pop_back();
else
{
for (auto tmp : lis)
addr[tmp] = 0 ;
return true ;
}
}
}
return false ;
}
bool canPartitionKSubsets(vector<int>& nums, int k) {
vector<int> addr(nums.size() , 1) ;
vector<int> lis ;
map<int, int> data ;
int sum = 0 , aver = 0 ;
for (auto tmp : nums)
{
sum += tmp ;
data[tmp] ++ ;
}
if (sum % k)
return false ;
//方式1的判断
bool station = true ;
for (auto tmpm : data)
if (tmpm.second % k)
station = false ;
if (station)
return true ;
//方式2:
aver = sum / k ;
sort(nums.begin() , nums.end()) ;
int c_i = 0 ;
for(c_i = nums.size() - 1 ; c_i > -1 ; c_i --)
{
if (addr[c_i])
{
if (nums[c_i] > aver)
return false ;
else
{
lis.push_back(c_i) ;
if (!judgeYes(nums , addr , lis , aver , c_i))
return false ;
else
k -- ;
lis.clear() ;
}
}
}
return true ;
}
};