[Java] Easy to understand commented DP
Initialize the mask to (1 << N) - 1 to so that the mask will start as 11...11, the 1\'s represent that the number at that index can still be used for a group.  
1. Initialize the mask to ```(1 << N) - 1``` to so that the mask will start as ```11...11```, the 1\'s represent that the number at that index can still be used for a group.  \n\n2. For each valid mask generate all possible combinations of bits of size ```S=N/k``` (Creating combinations of size S is extremely important since then we don\'t need to keep track of which numbers have already been used in the current group in our state) which we can then transform it into a mask representing the combination, e.g. if ```mask=111``` and ```S=2``` then we can have possible combinations: ```011, 101, 110```\n\n3. XOR the combination mask with the original mask to remove those elements from the next state and continue the recursion.\n\n4. Base case when ```mask==0``` since then every number has been used\n\n```Java\nclass Solution {\n    final int INF = (int)(1e5 + 7);\n    int N, S;\n    Integer[] dp;\n    int[] vals;\n    \n    public int minimumIncompatibility(int[] nums, int k) {\n        N = nums.length;\n        S = N / k;\n        dp = new Integer[1 << N];\n        Arrays.sort(nums);\n        vals = nums;\n        \n        int ans = recurse(nums, (1 << N) - 1);\n        \n        return ans == INF ? -1 : ans;\n    }    \n    \n    private int recurse(int[] nums, int mask) {\n        if (mask == 0) {\n            return 0;\n        }\n        else if (dp[mask] != null) {\n            return dp[mask];\n        }\n        \n        int ans = INF;\n        \n        //Get the indices of all bits that are set, these represent the numbers in the array that we can still select.\n        //Then generate all possible combinations of these indices\n        List<Integer> indices = getAvailableIndices(mask);\n        List<List<Integer>> combinations = new ArrayList<List<Integer>>();\n        generateCombinations(combinations, indices, new ArrayList<Integer>(), 0);\n        int numCombinations = combinations.size();\n        \n        for (int i = 0; i < numCombinations; i++) {\n            List<Integer> currentCombination = combinations.get(i);\n\n            int removedMask = 0;\n\n            //OR all the bits that we will be removing\n            for (int j = 0; j < S; j++) {\n                removedMask |= 1 << currentCombination.get(j);\n            }\n\n            //since array is sorted and the combinations traversing the array from left to right,\n            //the smallestIndex corresponds to the smallest number and the same argument applies for the largest number.\n            int smallestIndex = currentCombination.get(0);\n            int largestIndex = currentCombination.get(S - 1);\n\n            int smallestNumber = nums[smallestIndex];\n            int largestNumber = nums[largestIndex];\n\n            //Use XOR between mask and removedMask to turn off the bits that we used.\n            ans = Math.min(ans, largestNumber - smallestNumber + recurse(nums, mask ^ removedMask));\n        }\n        \n        return dp[mask] = ans;\n    }\n    \n    private List<Integer> getAvailableIndices(int mask) {\n        List<Integer> indices = new ArrayList<Integer>();\n        \n        //Check to see which bits are set, e.g. 101 => bits 2 and 0 are set.\n        for (int i = 0; i < N; i++) {\n            if ((mask & (1 << i)) != 0) {\n                indices.add(i);             \n            }\n        }\n        \n        return indices;\n    }\n    \n    private void generateCombinations(List<List<Integer>> combinations, List<Integer> indices, List<Integer> cur, int ind) {\n        if (cur.size() == S) {\n            combinations.add(cur);\n            return;\n        }\n        else if (ind == indices.size()) {\n            return;\n        }\n        \n        //Add this index to the current combination\n        List<Integer> copy = new ArrayList<Integer>(cur);\n        copy.add(indices.get(ind));\n        int newInd = ind + 1;\n        \n        //avoid duplicates\n        while (newInd < indices.size() && vals[indices.get(newInd)] == vals[indices.get(ind)]) newInd++;\n        generateCombinations(combinations, indices, copy, newInd);\n        \n        \n        //skip this index\n        copy = new ArrayList<Integer>(cur);\n        generateCombinations(combinations, indices, copy, ind + 1);\n    }\n}\n```
[]