阅读 95

77. 组合

题目描述

给定两个整数 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;
}
复制代码
文章分类
后端
文章标签