Leetcode 698. Divided into k equal subsets

Keywords: REST

1. Title Description

Given an integer array nums and a positive integer k, find out whether it is possible to divide the array into k non empty subsets, the sum of which is equal.

Example 1:

Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
Output: True
Note: it is possible to divide it into four subsets (5), (1,4), (2,3), (2,3) equal to the sum.
 

Be careful:

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

2. Solutions

This problem gives us an array of nums and a number k, and asks us whether the number can be divided into k non empty subsets so that the sum of each subset is the same. The range given for K is [1,16], and the numbers in the array are all positive. This is the same as before Partition Equal Subset Sum It's very similar, but that problem is only divided into two subsets, so the problem can be transformed into whether there is a subset and it is half of the sum of the whole array, which can be done with dp. But this problem makes it impossible to find k and the same, because even if one is found, the rest needs to be verified.

We can use recursion to solve this problem. First of all, we will find the sum of all the numbers in the array. First, we will judge whether sum can divide k or not. If not, we will directly return false.

Then we need a visited array to record which arrays have been selected, and then call the recursive function. Our goal is to set up the K subset, and the sum of each subset is target = sum/k. We also need the variable start to start searching from a certain position of the array. Cursum is the sum of the current subsets. In the recursive function, if k=0 and len(vis) = = len(nums): returns true directly. If cursum is equal to target, then we call recursion again. At this time, k-1 is passed in, and start and cursum are reset to 0. Because we have found another subset with and as target, we need to start looking for the next one. Otherwise, the array will be traversed from start. If the current number has been accessed, it will be skipped directly. Otherwise, it will be marked as accessed. Then calling the recursive function, K remains unchanged, because it is accumulating the current subset, start is passed to i+1, and curSum is sent to curSum+nums[i], because to accumulate the current number, if the recursive function returns true, it will return to true directly. Otherwise, the current number will be reset to the unreachable state to continue traversal, as shown in the following code:

3. Code implementation

class Solution(object):

    def dfs(self,nums,target,tmp,begin,k,vis):
        if k == 0 and len(vis) == len(nums):
            print "jin"
            return True
        for i in range(begin,len(nums)):
            if i not in vis:
                if tmp + nums[i]> target:
                    continue
                elif tmp + nums[i] == target:
                    vis.add(i)
                    if self.dfs(nums,target,0,0,k-1,vis):
                        return True
                    vis.remove(i)
                else:
                    vis.add(i)
                    if self.dfs(nums,target,tmp + nums[i],i+1,k,vis):
                        return True
                    vis.remove(i)

            


    def canPartitionKSubsets(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        s = sum(nums)
        if s%k != 0:
            return False
        target = s/k
        vis=set()
        flag = False
        flag = self.dfs(nums,target,0,0,k,vis)
        if flag:
            return True
        else:
            return False

Optimization: reverse order

class Solution(object):

    def dfs(self,nums,target,tmp,begin,k,vis):
        if k == 0 and len(vis) == len(nums):
            return True
        for i in range(begin,len(nums)):
            if i not in vis:
                if tmp + nums[i]> target:
                    continue
                elif tmp + nums[i] == target:
                    vis.add(i)
                    if self.dfs(nums,target,0,0,k-1,vis):
                        return True
                    vis.remove(i)
                else:
                    vis.add(i)
                    if self.dfs(nums,target,tmp + nums[i],i+1,k,vis):
                        return True
                    vis.remove(i)

            


    def canPartitionKSubsets(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        s = sum(nums)
        if s%k != 0:
            return False
        target = s/k
        vis=set()
        nums.sort(reverse=True)
        flag = False
        flag = self.dfs(nums,target,0,0,k,vis)
        if flag:
            return True
        else:
            return False

 

Published 240 original articles, won praise 6, visited 6859
Private letter follow

Posted by bad_gui on Sun, 23 Feb 2020 02:33:41 -0800