All k-Element Combinations From 1..n
Problem
Return every strictly increasing length-k sequence from 1..n. The result is C(n, k) tuples.
Recurse with the next allowed start. At each level, iterate i = start..n, append i, recurse with start i + 1, then pop. Pruning: stop the loop early when the remaining numbers cannot fill the remaining slots, i.e. when i > n - (k - len) + 1.
Input
n = 4, k = 2Output
[1,2] [1,3] [1,4] [2,3] [2,4] [3,4]Six combinations — C(4,2). Order within a tuple is increasing; the recursion guarantees this.
def combine(n, k):
out, path = [], []
def back(start):
if len(path) == k:
out.append(path.copy()); return
end = n - (k - len(path)) + 1
for i in range(start, end + 1):
path.append(i)
back(i + 1)
path.pop()
back(1)
return out
function combine(n, k) {
const out = [], path = [];
function back(start) {
if (path.length === k) { out.push(path.slice()); return; }
const end = n - (k - path.length) + 1;
for (let i = start; i <= end; i++) {
path.push(i);
back(i + 1);
path.pop();
}
}
back(1);
return out;
}
List<List<Integer>> out = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
back(1, n, k);
return out;
}
void back(int start, int n, int k) {
if (path.size() == k) { out.add(new ArrayList<>(path)); return; }
int end = n - (k - path.size()) + 1;
for (int i = start; i <= end; i++) {
path.add(i);
back(i + 1, n, k);
path.remove(path.size() - 1);
}
}
vector<vector<int>> out;
vector<int> path;
void back(int start, int n, int k) {
if ((int)path.size() == k) { out.push_back(path); return; }
int end = n - (k - (int)path.size()) + 1;
for (int i = start; i <= end; i++) {
path.push_back(i);
back(i + 1, n, k);
path.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
back(1, n, k);
return out;
}