package class_2023_05_2_week; import java.util.Arrays; // 给定一个整数数组 nums 和一个正整数 k, // 找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。 // 测试链接 : https://leetcode.cn/problems/partition-to-k-equal-sum-subsets/ public class Code04_PartitionToKEqualSumSubsets { // 状态压缩的方法,正统,处理不了大长度 // 其实任何方法都处理不了 public static boolean canPartitionKSubsets1(int[] nums, int k) { int sum = 0; for (int num : nums) { sum += num; } if (sum % k != 0) { return false; } return process1(nums, 0, 0, 0, sum / k, k, new int[1 << nums.length]) == 1; } public static int process1(int[] nums, int status, int sum, int sets, int limit, int k, int[] dp) { if (dp[status] != 0) { return dp[status]; } int ans = -1; if (sets == k) { ans = 1; } else { for (int i = 0; i < nums.length; i++) { if ((status & (1 << i)) == 0 && sum + nums[i] <= limit) { if (sum + nums[i] == limit) { ans = process1(nums, status | (1 << i), 0, sets + 1, limit, k, dp); } else { ans = process1(nums, status | (1 << i), sum + nums[i], sets, limit, k, dp); } if (ans == 1) { break; } } } } dp[status] = ans; return ans; } public static boolean canPartitionKSubsets2(int[] nums, int k) { int sum = 0; for (int num : nums) { sum += num; } if (sum % k != 0) { return false; } Arrays.sort(nums); return partitionK(new int[k], sum / k, nums, nums.length - 1); } // 100 10 -> 10 // 100 2 -> 50 // 100 4 -> 25 // 当前的数字,nums[index] // nums[n-1] 给哪个桶 // nums[n-2] 给哪个桶 // ... // nums[0] 给哪个桶 public static boolean partitionK(int[] group, int target, int[] nums, int index) { if (index < 0) { return true; } int num = nums[index]; // len是桶的数量! 就是k int len = group.length; for (int i = 0; i < len; i++) { if (group[i] + num <= target) { // 放入后,不超 group[i] += num; if (partitionK(group, target, nums, index - 1)) { return true; } group[i] -= num; // if (group[i] == 0) { // return false; // } while (i + 1 < group.length && group[i] == group[i + 1]) { i++; } } } return false; } }