How to iteratively generate k elements subsets from a set of size n in java?

后端 未结 7 1797
忘掉有多难
忘掉有多难 2020-11-29 09:14

I\'m working on a puzzle that involves analyzing all size k subsets and figuring out which one is optimal. I wrote a solution that works when the number of subsets is small,

7条回答
  •  感情败类
    2020-11-29 09:53

    Inspired by afsantos's answer :-)... I decided to write a C# .NET implementation to generate all subset combinations of a certain size from a full set. It doesn't need to calc the total number of possible subsets; it detects when it's reached the end. Here it is:

    public static List generateAllSubsetCombinations(object[] fullSet, ulong subsetSize) {
        if (fullSet == null) {
            throw new ArgumentException("Value cannot be null.", "fullSet");
        }
        else if (subsetSize < 1) {
            throw new ArgumentException("Subset size must be 1 or greater.", "subsetSize");
        }
        else if ((ulong)fullSet.LongLength < subsetSize) {
            throw new ArgumentException("Subset size cannot be greater than the total number of entries in the full set.", "subsetSize");
        }
    
        // All possible subsets will be stored here
        List allSubsets = new List();
    
        // Initialize current pick; will always be the leftmost consecutive x where x is subset size
        ulong[] currentPick = new ulong[subsetSize];
        for (ulong i = 0; i < subsetSize; i++) {
            currentPick[i] = i;
        }
    
        while (true) {
            // Add this subset's values to list of all subsets based on current pick
            object[] subset = new object[subsetSize];
            for (ulong i = 0; i < subsetSize; i++) {
                subset[i] = fullSet[currentPick[i]];
            }
            allSubsets.Add(subset);
    
            if (currentPick[0] + subsetSize >= (ulong)fullSet.LongLength) {
                // Last pick must have been the final 3; end of subset generation
                break;
            }
    
            // Update current pick for next subset
            ulong shiftAfter = (ulong)currentPick.LongLength - 1;
            bool loop;
            do {
                loop = false;
    
                // Move current picker right
                currentPick[shiftAfter]++;
    
                // If we've gotten to the end of the full set, move left one picker
                if (currentPick[shiftAfter] > (ulong)fullSet.LongLength - (subsetSize - shiftAfter)) {
                    if (shiftAfter > 0) {
                        shiftAfter--;
                        loop = true;
                    }
                }
                else {
                    // Update pickers to be consecutive
                    for (ulong i = shiftAfter+1; i < (ulong)currentPick.LongLength; i++) {
                        currentPick[i] = currentPick[i-1] + 1;
                    }
                }
            } while (loop);
        }
    
        return allSubsets;
    }
    

提交回复
热议问题