Leetcode 698.Partition to K Equal Sum Subsets(划分为K个相等的子集)

题目描述:

Given an array of integers nums and a positive integer k, find whether it's possible to divide this array into k non-empty subsets whose sums are all equal.

(给定一个整数数组  nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。)

Example 1:

 

Note:

  • 1 <= k <= len(nums) <= 16.
  • 0 < nums[i] < 10000.

思路:

该题目可以用深度优先搜索算法。

先计算出子序列的目标序列和target,即用数组nums的总和除以k,如果余数不为0,说明nums不可能被分成k个总和相等的非空子集,返回false。

否则,从nums数组的第一个元素开始,寻找加和等于target的元素的组合,组合中的元素被标记,不参与下一轮的选取;当选出一组子序列后,重新从nums数组的第一个元素开始,从未被标记的元素中继续寻找符合要求的子序列。

直到所有的元素被标记,并且找到了k个加和等于target子序列,才返回true,其余的情况都返回false。

扫描二维码关注公众号,回复: 5679608 查看本文章

实现(C++):

class Solution {
    public:
    bool canPartitionKSubsets(vector<int>& nums, int k) {
        if(k==1)
          return true;  
        
        if(k>nums.size())
            return false;
        
        int sum=0;        
        for(int i=0; i<nums.size(); i++)
            sum+=nums[i];
        
        if(sum%k)
            return false;
           
        int target=sum/k; //子序列和的目标和
        int visited[nums.size()]; //访问标记数组
        memset(visited, 0, sizeof(int)*nums.size()); //visited数组的元素都初始化为0
        return dfs(nums,0,0,target,0,k,visited); //深度优先搜索,返回判断结果
    }
    
    public:
    bool dfs(vector<int>& nums, int start, int n, int target, int sub_sum, int             k, int visited[])
    {   
        //nums    nums数组
        //start   本次深搜的起始位置
        //n       记录被访问元素的个数
        //target  子序列的目标和
        //sub_sum 当前的子序列和
        //k       当前还差k个目标和为target的子序列未被找到
        //visited 访问标记数组

        if(k==0&&n==nums.size())
        //如果已经凑齐所有目标和为target的子序列,并且nums数组的所有元素都被标记,返回true 
            return true;

        if(sub_sum==target)
        //如果找到一个和为target的子序列,则当前还差k-1个目标和为target的子序列未被找到,需要重新从nums数组的第一个元素开始,继续从未被标记的元素中寻找下一个目标和为target子序列 
            return dfs(nums,0,n,target,0,k-1,visited);  
        
        for(int i=start;i<nums.size();i++)
        {
            if(visited[i]==0) 
            {
                 if(sub_sum+nums[i]<=target){ 
                     visited[i]=1;  
                    
                     n=n+1;   
                 
                     //下一次递归从当前元素的下一个元素开始搜索,即start=i+1          
                     return dfs(nums,i+1,n,target,sub_sum+nums[i],k,visited);
  
                     n=n-1; //回溯
                     visited[i]=0;  
                }
            }
         }
        return false;
    }
};

猜你喜欢

转载自blog.csdn.net/Shishishi888/article/details/88838743