Home > OS >  All possible combinations and permutations of size n algorithm
All possible combinations and permutations of size n algorithm

Time:03-30

I'm trying to figure out an algorithm to have all possible combinations and permutations of size k from an array of size n.

Let's have an example:

Input:

n = 3 => [1, 2, 3]

Output should be:

k = 1 => [[1], [2], [3]]
k = 2 => [[1, 2], [1, 3], [2, 3], [2, 1], [3, 1], [3, 2]]
k = 3 => [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1 ,2], [3, 2, 1]]

I started by looking at the QuickPerm Algorithm but it gives all possible permutations for the size of the array:

If we go back to our example, the QuickPerm algorithm gives this output:

[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1 ,2], [3, 2, 1]].

CodePudding user response:

You can create all subsets of the given array and then apply quickPerm Algorithm on all the subsets.

subsets of [1,2,3] will be

[]
[1], [2], [3]
[1,2], [2,3], [3,1]
[1,2,3]

Now if you apply quickPerm on all these subsets, you'll get:

[]
[1], [2], [3]
[1,2], [2,1]
[2,3], [3,2]
[3,1], [1,3],
[1,2,3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1 ,2], [3, 2, 1]

You can club the results by using length of these vectors.

CodePudding user response:

Your task (all permutations of all combinations) can be easily solved using regular recursive function (as I did below) without any fancy algorithm.

Try it online!

#include <vector>
#include <functional>
#include <iostream>

void GenCombPerm(size_t n, size_t k, auto const & outf) {
    std::vector<bool> used(n);
    std::vector<size_t> path;
    std::function<void()> Rec =
        [&]{
            if (path.size() >= k) {
                outf(path);
                return;
            }
            for (size_t i = 0; i < used.size();   i) {
                if (used[i])
                    continue;
                used[i] = true;
                path.push_back(i);
                Rec();
                path.pop_back();
                used[i] = false;
            }
        };
    Rec();
}

int main() {
    std::vector<size_t> a = {1, 2, 3};
    GenCombPerm(a.size(), 2, [&](auto const & v){
        std::cout << "[";
        for (auto i: v)
            std::cout << a[i] << ", ";
        std::cout << "], ";
    });
}

Output:

[1, 2, ], [1, 3, ], [2, 1, ], [2, 3, ], [3, 1, ], [3, 2, ], 

CodePudding user response:

class CombinationsPermutation {
public:
    explicit CombinationsPermutation(size_t n, size_t k)
        : n { n }
    {
        indexes.resize(k);
        reset();
    }

    void reset()
    {
        std::iota(indexes.begin(), indexes.end(), 0);
    }

    const std::vector<size_t>& get() const
    {
        return indexes;
    }

    bool next()
    {
        if (std::next_permutation(indexes.begin(), indexes.end())) {
            return true;
        }
        auto it = indexes.rbegin();
        auto max_index = n - 1;
        while (it != indexes.rend() && *it == max_index) {
            --max_index;
              it;
        }
        if (it != indexes.rend()) {
            std::iota(it.base() - 1, indexes.end(), *it   1);
            return true;
        }
        reset();
        return false;
    }

private:
    size_t n;
    std::vector<size_t> indexes;
};

https://godbolt.org/z/dex634fY1

  • Related