文章目录
- 1. 题目
- 2. 解题
1. 题目
给你一个整数数组 nums 和一个整数 k 。你需要将这个数组划分到 k 个相同大小的子集中,使得同一个子集里面没有两个相同的元素。
一个子集的 不兼容性 是该子集里面最大值和最小值的差。
请你返回将数组分成 k 个子集后,各子集 不兼容性 的 和 的 最小值 ,如果无法分成分成 k 个子集,返回 -1 。
子集的定义是数组中一些数字的集合,对数字顺序没有要求。
示例 1:
输入:nums = [1,2,1,4], k = 2
输出:4
解释:最优的分配是 [1,2] 和 [1,4] 。
不兼容性和为 (2-1) + (4-1) = 4 。
注意到 [1,1] 和 [2,4] 可以得到更小的和,但是第一个集合有 2 个相同的元素,所以不可行。示例 2:
输入:nums = [6,3,8,1,3,1,2,2], k = 4
输出:6
解释:最优的子集分配为 [1,2],[2,3],[6,8] 和 [1,3] 。
不兼容性和为 (2-1) + (3-2) + (8-6) + (3-1) = 6 。示例 3:
输入:nums = [5,3,3,6,3,3], k = 3
输出:-1
解释:没办法将这些数字分配到 3 个子集且满足每个子集里没有相同数字。提示:
1 <= k <= nums.length <= 16
nums.length 能被 k 整除。
1 <= nums[i] <= nums.length
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-incompatibility
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题
写的回溯,超时了,参考评论区的刘波
同学的代码,做了剪枝,通过了
class Solution {int mindiff = INT_MAX;int size;//每个集合的大小
public:int minimumIncompatibility(vector<int>& nums, int k) {if(k == nums.size())//特殊情况return 0;unordered_map<int, int> m;sort(nums.begin(), nums.end());for(auto n : nums){if(++m[n] > k)return -1;}size = nums.size()/k;vector<int> curnum(k), count(k, 0);//每个集合当前的数,集合大小dfs(nums, curnum, count, 0, 0);return mindiff;} void dfs(vector<int>& nums, vector<int>& curnum, vector<int>& count, int i, int diff){if(diff >= mindiff)//剪枝return;if(i == nums.size()){if(diff < mindiff)mindiff = diff;return;}for(int j = 0; j < count.size(); ++j){if(curnum[j] == nums[i])//存在相同的数字了continue;if(count[j] < size)//集合还没满{int originnum = curnum[j];//集合当前的数字curnum[j] = nums[i];//nums[i] 放入集合 jcount[j]++;//集合大小 + 1int delta = count[j] >= 2 ? (nums[i]-originnum) : 0;// diff 增量dfs(nums, curnum, count, i+1, diff+delta);count[j]--;curnum[j] = originnum;if(count[j] == 0)//参考 刘波 同学//都是空的集合,这个数字放在哪个集合都是一样的,不写这句,会超时break;}}}
};// 28 ms 7.6 MB C++
28 ms 7.6 MB C++
我的CSDN博客地址 https://michael.blog.csdn.net/
长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!