給定 n 個互不相同元素,求所有選取 k 個元素的組合(順序無關)。例如 {1,2,3,4} 選 2:{1,2}, {1,3}, {1,4}, {2,3}, {2,4}, {3,4}。
「以某元素為首」+「從其後元素中選 k-1 個」。
combine([1,2,3,4], 2) = 1 + combine([2,3,4], 1) = 2 + combine([3,4], 1) = 3 + combine([4], 1) = 4 + combine([], 1) → 終止(剩餘不足)
#include <stdio.h>
#include <string.h>
#define MAX_N 20
int g_combination[MAX_N];
int g_top = 0;
// 打印當前組合
void print_combination() {
for (int i = 0; i < g_top; ++i)
printf("%d ", g_combination[i]);
printf("\n");
}
// 遞歸生成
// data: 待選元素陣列起始位址
// len: 待選元素個數
// k: 尚需選取個數
void combine(int data[], int len, int k) {
if (k == 0) { // 已選夠 k 個
print_combination();
return;
}
if (len < k) return; // 剩餘元素不足,剪枝
for (int i = 0; i < len; ++i) {
g_combination[g_top++] = data[i]; // 選擇 data[i]
combine(data + i + 1, len - i - 1, k - 1); // 從後續元素選 k-1
--g_top; // 回溯
}
}
int main() {
int data[] = {1, 2, 3, 4, 5, 6};
int n = sizeof(data) / sizeof(int);
int k = 4;
memset(g_combination, 0, sizeof(g_combination));
combine(data, n, k);
return 0;
}
g_combination 記錄當前路徑,g_top 模擬堆疊指標。data + i + 1 確保不重複、不倒序;len - i - 1 更新剩餘可選數量;k - 1 更新仍需選取數。if (len < k) return; 避免無效遞歸。k == 0 表示組合完成,打印結果。修改 data 與 k,對照數學計算結果:
data + i + 1 限制,改用 used[] 標記數組。組合生成是回溯法的經典入門。核心模板:選擇 → 遞歸 → 撤銷選擇。掌握此模式,可解決 LeetCode 77、39、40 等大類組合/子集問題。