【力扣】DP/贪心:1681. 最小不兼容性
文章目录
- 【力扣】DP/贪心:1681. 最小不兼容性
 - 1. 题目描述
 - 2. 解题
 - 2.1 不可行
 - 2.2 DP(预处理 + 状态压缩 + 动态规划)
 
- 参考
 
1. 题目描述
给你一个整数数组 nums 和一个整数 k 。你需要将这个数组划分到 k 个相同大小的子集中,使得同一个子集里面没有两个相同的元素。
- 一个子集的 不兼容性 是 该子集里面最大值和最小值的差。
 
请你返回将数组分成 k 个子集后,各子集 不兼容性 的 和 的 最小值 ,如果无法分成分成 k 个子集,返回 -1 。
 子集的定义是数组中一些数字的集合,对数字顺序没有要求。
 
2. 解题
2.1 不可行
首先想到先排个序,再贪心就好了,但是这种情况【1,1,2,2,3,3】,就得回溯。
-  
改进,但未实现。
- 先判断是否满足条件,即判断每个数的个数是否小于 k,不满足直接输出-1;
 - 然后排序+贪心?+回溯+剪枝。
 
 -  
之前版本代码(错误的)。
 
class Solution {
public:
    int minimumIncompatibility(vector<int>& nums, int k) {
        int n = nums.size();
        int l = n / k;
        sort(nums.begin(), nums.end());
        vector<int> flags(n, 0);
        vector<int> cur(l, 0);
        int flag = 0;
        int sum = 0;
        for(int i=0; i<n; i++){
            cout<<nums[i];
        }
        cout<<endl;
        for(int i=0; i<n; i++){
            cout<<n<<"  00000"<<endl;
            if(flags[i]==1){
                continue;
            }
            int h = i;
            int cnt = 0;
            int ct = 0;
            while(cnt<l){
                int f = 0;
                if(flags[h]==1){
                    h++;
                    continue;
                }
                for(int j=0; j<cnt; j++){
                    cout<<"abc"<<j<<h<<endl;
                    cout<<cur[j]<<nums[h]<<endl;
                    if(cur[j]==nums[h]){
                        f = 1;
                        break;
                    }
                }
                cout<<f<<'h'<<h<<endl;
                if(flag==1) break;
                if(f==0){
                    cur[cnt] = nums[h];
                    cnt++;
                    flags[i] = 1;
                    if(h<n-1){
                        h++;
                    }
                    else{
                        break;
                    }
                }
                else{
                    h++;
                }
            }
            sum += (cur[l-1] - cur[0]);
        }
        if(flag == 1){
            sum = -1;
        }
        return sum;
    }
};
 
2.2 DP(预处理 + 状态压缩 + 动态规划)
- 正确题解是DP(预处理 + 状态压缩 + 动态规划)

 
class Solution:
    def minimumIncompatibility(self, nums: List[int], k: int) -> int:
        n = len(nums)
        m = n // k
        g = [-1] * (1 << n)
        for i in range(1, 1 << n):
            if i.bit_count() != m:
                continue
            s = set()
            mi, mx = 20, 0
            for j, x in enumerate(nums):
                if i >> j & 1:
                    if x in s:
                        break
                    s.add(x)
                    mi = min(mi, x)
                    mx = max(mx, x)
            if len(s) == m:
                g[i] = mx - mi
        f = [inf] * (1 << n)
        f[0] = 0
        for i in range(1 << n):
            if f[i] == inf:
                continue
            s = set()
            mask = 0
            for j, x in enumerate(nums):
                if (i >> j & 1) == 0 and x not in s:
                    s.add(x)
                    mask |= 1 << j
            if len(s) < m:
                continue
            j = mask
            while j:
                if g[j] != -1:
                    f[i | j] = min(f[i | j], f[i] + g[j])
                j = (j - 1) & mask
        return f[-1] if f[-1] != inf else -1
 
参考
【1】https://leetcode.cn/problems/minimum-incompatibility/description/


















