###### tags: `LeetCode` `Medium` `DFS`
# LeetCode #698 [Partition to K Equal Sum Subsets](https://leetcode.com/problems/partition-to-k-equal-sum-subsets/)
### (Medium)
給定一個整數數組 nums 和一個正整數 k,找出是否有可能把這個數組分成 k 個非空子集,其總和都相等。
---
首先可以先將nums排序, 並計算總和以及每個組合的元素和, 若元素和不為整數則回傳空集合。
接下來使用DFS找組合, 每找到一組則從頭開始尋找新的組合, 並將組合數+1, 若組合數等同於k, 則回傳true, 若找完全部組合皆沒達成組合數等於k, 則回傳false。
幾個要點:
1. 當找到新的組合時(sum==total/k), 要回傳的是從頭開始, 但組合數+1的DFS
2. 由於找到新的組合後須從頭開始找, 因此不能用`if(i!=pos&&nums[i]==nums[i-1])continue;`來跳過重複值, 這會跳過所有不是第一個的重複值, 而非其原本的用意: 在DFS探索失敗"返回"後, 跳過探索必定失敗的重複值。
差別在於這題是探索成功後尋找其他組合, 而非探索失敗後"返回"再尋找其他組合。因此本題需要使用last來辨識用過的值。
---
```
class Solution {
public:
int total;
int visited[16];
int k;
bool canPartitionKSubsets(vector<int>& nums, int k) {
this->k = k;
total = accumulate(nums.begin(), nums.end(), 0);
sort(nums.begin(), nums.end());
if(total%k!=0)return false;
return dfs(0,0,0, nums);//pos, group, sum
}
bool dfs(int pos, int group, int sum, vector<int>& nums){
if(sum>total/k)return false;
if(sum==total/k)return dfs(0, group+1, 0, nums);
if(group==k)return true;
int last=-1;
for(int i=pos;i<nums.size();i++){
if(visited[i])continue;
//if(i!=pos&&nums[i]==nums[i-1])continue;//不能這樣寫
if(nums[i]==last)continue;
visited[i]=1;
last=nums[i];
if(dfs(i+1, group, sum+nums[i], nums))return true;
visited[i]=0;
}
return false;
}
};
```