# 77. 组合

### 实现

``````// 结果的个数为n个数中选k个，排列组合公式计算
int getVal(int n, int k)
{
// n! / (k! * (n-k)!) = n * (n-1) *...* (n-k+1) / k! = n * (n-1) * (k+1) / (n-k)!
// 防越界，所以乘到较大数(少乘一点)
int nSum = 1;
int kSum = 1;
if (k > n - k) {
for (int i = k + 1; i <= n; i++) {
nSum *= i;
}
for (int i = 1; i <= n - k; i++) {
kSum *= i;
}
} else {
for (int i = n - k + 1; i <= n; i++) {
nSum *= i;
}
for (int i = 1; i <= k; i++) {
kSum *= i;
}
}

int res = nSum / kSum;
return res;
}

void backtracking(int n, int k, int *returnSize, int **returnColumnSizes, int num, int *numList, int idx, int **result)
{
if (num == k) {    // 已经选中了k个，保存当前这个记录并返回
result[*returnSize] = (int*)malloc(sizeof(int) * num);
for (int i = 0; i < num; i++) {
result[*returnSize][i] = numList[i];
}
(*returnColumnSizes)[*returnSize] = num;
(*returnSize)++;
return;
}

for (int i = idx; i <= n; i++) {    // 从1到n选择
numList[num++] = i;    // 当前再加一个数字
backtracking(n, k, returnSize, returnColumnSizes, num, numList, i + 1, result);
num--;
}
}

// 需要定义一个数组，用来保存每一个取得的数字
int **combine(int n, int k, int *returnSize, int **returnColumnSizes)
{
*returnSize = 0;
if (n < k) {
returnColumnSizes = NULL;
return NULL;
}
*returnColumnSizes = (int*)malloc(sizeof(int) * getVal(n, k));
memset(*returnColumnSizes, 0, sizeof(int) * getVal(n, k));
int **result = (int**)malloc(sizeof(int*) * getVal(n, k));
memset(result, 0, sizeof(int*) * getVal(n, k));
if (n == k) {
*returnSize = 1;
(*returnColumnSizes)[0] = k;
result[0] = (int*)malloc(sizeof(int) * k);
for (int i = 0; i < k; i++) {
result[0][i] = i + 1;
}
return result;
}
int num = 0;    // 当前选中了几个元素
int *numList = (int*)malloc(sizeof(int) * (k + 1));    // 这里之所以用k+1没有用k是因为backtracking中的for循环中当i值为3时
memset(numList, 0, k);
backtracking(n, k, returnSize, returnColumnSizes, num, numList, 1, result);    // 1表示从1开始
return result;
}