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之路的主要内容,如果未能解决你的问题,请参考以下文章

698. 划分为k个相等的子集(Python)

LeetCode 1624. 两个相同字符之间的最长子字符串 / 698. 划分为k个相等的子集 / 面试题 01.08. 零矩阵 / 1694. 重新格式化电话号码

LeetCode 1624. 两个相同字符之间的最长子字符串 / 698. 划分为k个相等的子集 / 面试题 01.08. 零矩阵 / 1694. 重新格式化电话号码

Leetcode——划分为k个相等的子集(目标和)

leetcode 698 集合k划分

划分为k个相等的子集