698. Partition to K Equal Sum Subsets

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.

Example 1:

Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
Output: True
Explanation: It's possible to divide it into 4 subsets (5), (1, 4), (2,3), (2,3) with equal sums.

Note:

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

Approach #1: DFS + Backtracking. [C++]

class Solution {
public:
    bool canPartitionKSubsets(vector<int>& nums, int k) {
        int len = nums.size();
        if (k == 1) return true;
        if (len < k) return false;  
        
        int sum = 0;
        for (int num : nums)
            sum += num;
        if (sum % k != 0) return false;
        
        int avg = sum / k;
        vector<int> token(len+5, 0), subsets(k+5, 0);
        subsets[0] = nums[len-1];
        token[len-1] = 1;
        return solve(nums, token, subsets, avg, k, len, 0, len-1);
    }
    
private:
    bool solve(vector<int>& nums, vector<int>& token, vector<int>& subsets,
               const int& avg, const int& k, const int& len, int curIdx, int limitIdx) {
        if (subsets[curIdx] == avg) {
            if (curIdx == k-2) return true;
            return solve(nums, token, subsets, avg, k, len, curIdx+1, len-1);
        }
        
        for (int i = limitIdx; i >= 0; --i) {
            if (token[i] == 1) continue;
            int tmp = subsets[curIdx] + nums[i];
            
            if (tmp <= avg) {
                subsets[curIdx] += nums[i];
                token[i] = 1;
                bool nxt = solve(nums, token, subsets, avg, k, len, curIdx, i-1);
                subsets[curIdx] -= nums[i];
                token[i] = 0;
                if (nxt) return true;
            }
        }
        
        return false;
    }
};

  

Analysis:

We can solve this problem recursively, we keep an array for sum of each partition and a array to check whether an element is already taken into some partition or not.

First we need to check some base cases:

If K is 1, then we already have our answer, complete array is only sbset with same sum.

If N < K, then it is not possible to divide array into subsets with equal sum, because we can't divide the array into more than N parts.

If sum of array is not divisible by K. then it is not possible to divide the array. We will proceed only if k divides sum. Our goal reduces to divide array into K parts where sum of each part should be array_sum / k

In above code  a recursive method is written which tries to add array element into some subset. If sum of this subset reaches required sum, we iterator for next part recursively, otherwise we backtrack for different set of elements. If number of subsets whose sum reaches the required sum is (K-1), we flag that it is possible to partition array nto K parts with equal sum, because remaining elements already have a sum equal to required sum.

Reference:

https://www.geeksforgeeks.org/partition-set-k-subsets-equal-sum/

永远渴望,大智若愚(stay hungry, stay foolish)
原文地址:https://www.cnblogs.com/h-hkai/p/10532684.html