LeetCode 698 划分为k个相等的子集[回溯 剪枝] HERODING的LeetCode之路
Posted HERODING23
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 698 划分为k个相等的子集[回溯 剪枝] HERODING的LeetCode之路相关的知识,希望对你有一定的参考价值。
解题思路:
是一道比较困难的中等题,首先简单判断子集的和是否能够被k整除,能整除得到整除的数target,然后从大到小排序看最大的数是否小于target,否则返回false,这里从大到小排序很讲究,否则会超时,因为先装大的再装小的可以让每个桶都很平均,减少了回溯时候循环的次数。桶定义好后,就从大到小把数往桶里装,超过了桶的大小就跳过,以及和前一个桶相等(前面没要后面自然也要不起)也要跳过,这两步剪枝都很重要,最后所有的数都装进桶里返回true,代码如下:
class Solution
private:
vector<int> bucket;
int target;
public:
bool canPartitionKSubsets(vector<int>& nums, int k)
int n = nums.size();
int total = accumulate(nums.begin(), nums.end(), 0);
if(total % k > 0) return false;
// 从大到小排序,便于将所有桶都装快满
sort(nums.rbegin(), nums.rend());
target = total / k;
// 如果最大的数超过了桶能装的大小
if(nums[0] > target) return false;
bucket = vector<int>(k, 0);
return traceback(nums, 0);
bool traceback(vector<int>& nums, int index)
// 所有数都在bucket中,返回true
if(index == nums.size())
return true;
for(int i = 0; i < bucket.size(); i ++)
// 大了不要
if(bucket[i] + nums[index] > target)
continue;
// 和前面相等,前面没要后面自然也要不起
if(i != 0 && bucket[i] == bucket[i - 1])
continue;
bucket[i] += nums[index];
// 继续往下走,看是否能一直满足
if(traceback(nums, index + 1))
return true;
bucket[i] -= nums[index];
return false;
;
以上是关于LeetCode 698 划分为k个相等的子集[回溯 剪枝] HERODING的LeetCode之路的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 1624. 两个相同字符之间的最长子字符串 / 698. 划分为k个相等的子集 / 面试题 01.08. 零矩阵 / 1694. 重新格式化电话号码
LeetCode 1624. 两个相同字符之间的最长子字符串 / 698. 划分为k个相等的子集 / 面试题 01.08. 零矩阵 / 1694. 重新格式化电话号码