-2

unique numbers $1 - n$
combinations (sets) of size $k$
$k < n$

do not re-use an $n$ in a set [1, 1, 1] is not valid

How to generate all unique sets of size $k$?
[1,2,3] = [3,2,1] order does not matter

the number of sets will be ${\binom{n}{k}}$

input
$n = 4, k = 2$
output
[1, 2]
[1, 3]
[1, 4]
[2, 3]
[2, 4]
[3, 4]

I have found that is often called n chose k

hard coded it looks like

for (i = i; i <= n - 1; i++)  
    for (j = i + 1; j <= n - 1; j++)  

I tried coding the first solution from Yuval Filmus but it does not work for me
It returns [1,2], [1,2]
Had to adjust for 0 based arrays

public static void Combinations(int n, int k)
{
    bool[] A = new bool[n];
    int[] B = Enumerable.Range(1, k).ToArray();
    Generate(1, A, B, k, n);
}
public static void Generate(int l, bool[] A, int[] B, int k, int n)
{
    Debug.WriteLine(string.Join(", ", B));
    if (l == k + 1)
    {
        Debug.WriteLine("l == k + 1");
        return;
    }

    for (int i = 0; i < n; i++)
    {
        if (!A[i])
        {
            A[i] = true;
            B[l - 1] = i + 1;
            Generate(l + 1, A, B, k, n);
            A[i] = false;
        }
    }
}
paparazzo
  • 431
  • 3
  • 13

2 Answers2

1

Ordered combinations

Here is a simple recursive routine, which has access to a Boolean array $A$ of length $n$, whose initial entries have the value false, and to an integer array $B$ of length $k$. The routine is called with $\ell = 1$.

Generate($\ell$):

  • If $\ell=k+1$, output $B$, and exit the current recursive call.
  • Go over elements $i$ from $1$ to $n$:
    • If $A[i]$ is false:
      • Set $A[i]$ to true.
      • Set $B[\ell]$ to $i$.
      • Call Generate($\ell+1$).
      • Set $A[i]$ to false.

The array $B$ consists of the current tuple, and the array $A$ keeps track of which elements are currently used (this is an optimization, since the information can be gleaned from $k$).

It is possible to convert this algorithm to an iterative one, and to improve its complexity for large $k$ (in particular, for the extreme case $k=n$). Take a look at Section 7.2 of Volume 4A of Knuth's Art of Computer Programming (see here for table of contents).

Unordered combinations

These are somewhat simpler, since we don't need the array $A$. The recursive routine is called with $\ell=1$:

Generate($\ell$):

  • If $\ell = k+1$, output $B$, and exit the current recursive call.
  • If $\ell = 1$, set $\max$ to 0, otherwise set $\max$ to $B[\ell-1]$.
  • Go over all elements $i$ from $\max+1$ to $n-(k-\ell)$:
    • Set $B[\ell]$ to $i$.
    • Call Generate($\ell+1$).

This generates unordered combinations (like you asked in the question), each of them itself ordered. In the code, $\max$ is just the maximum element in the current tuple. You can also pass it as a parameter as in bstrauch24's answer.

Again, the algorithm can be made iterative, and Knuth (same place) has even more information.

Yuval Filmus
  • 280,205
  • 27
  • 317
  • 514
1

Here is a recursive solution in python:

n, k = 4, 2

def dfs(A, start):
    if len(A) == k:
        print(A)

    for i in range(start, n + 1):
        A.append(i)
        dfs(A, i + 1)
        A.pop()

dfs([], 1)
Brian
  • 119
  • 2