Given an array of integersnumsand a positive integerk, find whether it's possible to divide this array intoknon-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.
分析
此题DP不能做,只能DFS
DP:用01背包,尝试失败。
class Solution:
def canPartitionKSubsets(self, nums: List[int], k: int) -> bool:
sm = sum(nums)
if sm % k !=0:
return False
t = sm//4
n = len(nums)
f = [[False]*(t+1) for _ in range(k)]
for i in range(n):
for kk in range(k):
f[kk][0] = True
for v in range(t,nums[i]-1,-1):
f[kk][v] |= f[kk][v-nums[i]]
res = False
for i in range(k):
res |= f[i][t]
return res
dfs
和combination sum一样,只是target满了就移到下一组。
记住下一组nums从头起,要不nums有值跳过没取到。有seen不会重复
class Solution:
def canPartitionKSubsets(self, nums: List[int], k: int) -> bool:
sm = sum(nums)
if sm % k !=0:
return False
target = sm//k
n = len(nums)
seen =set()
#分成K组,每组还是combination sum
def dfs(cursum,ni,gi):
if gi == 1:
return True
if cursum == target:
return dfs(0,0,gi-1)#nums从0开始,有seen不怕重复
for i in range(ni,n):
if i not in seen:
seen.add(i)
if dfs(cursum+nums[i],i+1,gi):
return True
seen.remove(i)
return False
return dfs(0,0,k)
另一种dfs, loop groups
class Solution:
def canPartitionKSubsets(self, nums: List[int], k: int) -> bool:
target,rem = divmod(sum(nums), k)
if rem != 0:
return False
n = len(nums)
nums.sort(reverse=True)
groups = [target] * k
def dfs(pos):
if pos ==n:
return True
for i in range(k):
if nums[pos] <= groups[i]:
groups[i] -= nums[pos]
if dfs(pos+1):
return True
groups[i] += nums[pos]
return False
return dfs(0)