题目描述
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
示例
示例 1:
输入:n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
示例 2:
输入:n = 1, k = 1
输出:[[1]]
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/co…
实现
// 结果的个数为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;
}