Leetcode 698. 划分为k个相等的子集(中等) 回溯算法=集合划分

labuladong讲解

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

题目:

给你输入一个数组 nums 和一个正整数 k,请你判断 nums 是否能够被平分为元素和相同的 k 个子集。

 

思路:

我们切换到这 n 个数字的视角,每个数字都要选择进入到 k 个桶中的某一个。

使用递归,每次选择一个数,然后遍历桶,看将nums[index]放入哪个桶中可以得到正常结果。如果都不行,则证明不能均分。

如果我们让尽可能多的情况命中剪枝的那个 if 分支,就可以减少递归调用的次数,一定程度上减少时间复杂度。

如何尽可能多的命中这个 if 分支呢?要知道我们的 index 参数是从 0 开始递增的,也就是递归地从 0 开始遍历 nums 数组。

如果我们提前对 nums 数组排序,把大的数字排在前面,那么大的数字会先被分配到 bucket 中,对于之后的数字,bucket[i] + nums[index] 会更大,更容易触发剪枝的 if 条件。

复制代码
class Solution {
public:
    bool canPartitionKSubsets(vector<int>& nums, int k) {
        int n=nums.size();
        int sum=0;
        for(int i=0;i<n;++i){
            sum+=nums[i];
        }
        // 排除一些基本情况
        if(n<k||sum%k!=0) return false;
        // 理论上每个桶(集合)中数字的和
        int target=sum/k;
        // k 个桶(集合),记录每个桶装的数字之和
        vector<int> bucket(k);
        sort(nums.begin(),nums.end(),[](int a,int b){
            return a>b;
        });
        // 穷举,看看 nums 是否能划分成 k 个和为 target 的子集
        return backtrack(nums,bucket,0,target);
    }

    bool backtrack(vector<int>& nums,vector<int>& bucket, int index, int target) {
        if(index==nums.size()){
            // 检查所有桶的数字之和是否都是 target
            for(int i=0;i<bucket.size();++i){
                if(bucket[i]!=target){
                    return false;
                }
            }
            // nums 成功平分成 k 个子集
            return true;
        }
        // 穷举 nums[index] 可能装入的桶
        for(int i=0;i<bucket.size();++i){
            // 剪枝,桶装装满了
            if(bucket[i]+nums[index]>target){
                continue;
            }
            // 将 nums[index] 装入 bucket[i]
            bucket[i]+=nums[index];
            // 递归穷举下一个数字的选择
            if(backtrack(nums,bucket,index+1,target)){
                return true;
            }
            // 撤销选择
            bucket[i]-=nums[index];
        }
        // nums[index] 装入哪个桶都不行
        return false;
    }
};
复制代码

 

posted @   鸭子船长  阅读(112)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示