• 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;
        }
    };
  • 相关阅读:
    ps cc 2018安装
    eclipse 快速添加 set , get 方法
    电脑设置以太网
    C# 获取web.config配置文件内容
    C# @Page指令中的AutoEventWireup,CodeBehind,Inherits
    未能正确加载“Microsoft.VisualStudio.Implementation.EditorPackage”包
    C# 实现MD5加密
    mutex 简单介绍
    select @@IDENTITY
    C# vs2012创建报表
  • 原文地址:https://www.cnblogs.com/zl1991/p/15976139.html
Copyright © 2020-2023  润新知