这个题解使用了回溯算法和剪枝优化。首先计算数组元素总和是否能被k整除,如果不能则直接返回False。然后将数组按从大到小排序,便于剪枝。接着使用递归回溯,维护一个大小为k的数组cur,表示当前k个子集的和。对于每个数,依次尝试放入每个子集中,如果放入后子集和不超过目标和s,则递归到下一个数。如果递归到最后一个数,说明找到了一种合法方案,返回True。如果尝试了所有可能性都无法找到合法方案,则返回False。在递归过程中,如果当前子集和与前一个子集和相等,则可以跳过,因为这种情况已经被之前的分支考虑过了,这样可以去除重复计算,减少时间复杂度。
时间复杂度: O(k^n)
空间复杂度: O(n)
```python
class Solution:
def canPartitionKSubsets(self, nums: List[int], k: int) -> bool:
def dfs(i):
if i == len(nums): # 已经遍历完所有数
return True
for j in range(k): # 遍历k个子集
if j and cur[j] == cur[j - 1]: # 当前子集和与前一个相等,跳过
continue
cur[j] += nums[i] # 将当前数放入当前子集
if cur[j] <= s and dfs(i + 1): # 如果子集和不超过目标,递归到下一个数
return True
cur[j] -= nums[i] # 回溯,移除当前数
return False
s, mod = divmod(sum(nums), k)
if mod: # 总和不能被k整除,返回False
return False
cur = [0] * k # 初始化k个子集和为0
nums.sort(reverse=True) # 降序排列,便于剪枝
return dfs(0) # 从第0个数开始回溯
```