class Solution {
public boolean canPartitionKSubsets(int[] nums, int k) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if (sum % k != 0) {
return false;
}
Arrays.sort(nums); // prunin
reverse(nums);
return dfs(k, nums, 0, 0, new boolean[16], sum/k);
}
private boolean dfs(int k, int[] nums, int start, int sum, boolean[] visited, int mean) {
if (k == 0) {
return true;
}
// 換下個 group, set start = 0, sum = 0
// 為什麼可以設 start 從 0 開始跑呢, 因為有紀錄 visited, 所以使用過的, 會跳過, 所以從 0 開始
// sum = 0 很直觀, 因為要來計算下個 group 的和到 mean 了沒
if (sum == mean) {
return dfs(k-1, nums, 0, 0, visited, mean);
}
int last = -1;
for (int i = start; i < nums.length; i++) {
if (visited[i]) {
continue;
}
if (sum + nums[i] > mean) { // pruning
continue;
}
if (nums[i] == last) { // pruning : skip same number
continue;
}
visited[i] = true;
sum += nums[i];
last = nums[i];
if (dfs(k, nums, start + 1, sum, visited, mean)) {
return true;
}
sum -= nums[i];
visited[i] = false;
}
return false;
}
private void reverse(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
}
}