跳转至

LeetCode: 119. 杨辉三角 II

1、题目描述

给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。

img

在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

输入: 3
输出: [1,3,3,1]

进阶:

你可以优化你的算法到 O(k) 空间复杂度吗?

2、解题思路

​ 实际上,杨辉三角就是多项式的展开式的系数,

​ 因此,可以用组合公式直接求解

例如第一行

C^{0}_{0}

第二行

C^{0}_{1} C^{1}_{1}

第三行

C^{0}_{2} C^{1}_{2} C^{2}_{2}

因此,根据这个规律,以及对称性,只需要用公式将左半部分计算出来,右半部分直接赋值就好了

实际在实现的时候,发现在进行求组合的时候,出现了溢出,为了防止溢出,进行约分处理

约分的时候,为了效率起见,先求出了质数数组

#include <stdlib.h>
#include <stdbool.h>
#include "stdio.h"
#include "string.h"


struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};


int *findPrimes(int num, int *numSize) {
    if (num <= 1) {
        *numSize = 0;
        return NULL;
    }

    int *result = (int *) malloc(sizeof(int) * (num / 2 + 1));
    result[0] = 2;
    *numSize = 1;
    int cur_num = 3;
    bool isPrime = true;
    while (cur_num <= num) {
        isPrime = true;
        for (int i = 0; i < *numSize; i++) {
            if (cur_num % result[i] == 0) {
                isPrime = false;
                break;
            }
        }
        if (isPrime) {
            result[(*numSize)++] = cur_num;
        }
        cur_num++;
    }
    return result;
}


int combination(int total, int chose) {
    if (chose == 0) {
        return 1;
    } else if (chose == 1) {
        return total;
    }

    int total_left = total - chose > chose ? total - chose : chose;
    int chose_right = total - chose > chose ? chose : total - chose;

    // 找到所有小于chose_right 的质数
    int primeSize = 0;
    int *primes = findPrimes(chose_right, &primeSize);

    int *buff_total = (int *) malloc(sizeof(int) * (total - total_left));
    int *buff_chose = (int *) malloc((sizeof(int) * (chose_right - 1)));

    // 缓冲初始化
    for (int i = total_left + 1; i <= total; i++) {
        buff_total[i - total_left - 1] = i;
    }
    for (int i = 2; i <= chose_right; i++) {
        buff_chose[i - 2] = i;
    }


    // 进行约分
    bool reduction = false;
    while (!reduction) {
        reduction = true;
        for (int i = 0; i < chose_right - 1; i++) {
            for (int j = 0; j < primeSize; j++) {
                if (buff_chose[i] != 1 && buff_chose[i] % primes[j] == 0) {
                    buff_chose[i] /= primes[j];
                    for (int k = 0; k < total - total_left; k++) {
                        if (buff_total[k] != 1 && buff_total[k] % primes[j] == 0) {
                            buff_total[k] /= primes[j];
                            break;
                        }
                    }
                    if (buff_chose[i] != 1) {
                        reduction = false;
                    }
                    break;
                }
            }
        }
    }


    int result = 1;

    for (int i = 0; i < total - total_left; i++) {

        result *= buff_total[i];
    }

    free(buff_total);
    free(buff_chose);
    free(primes);
    return result;

}


int *getRow(int rowIndex, int *returnSize) {
    if (rowIndex < 0) {
        return NULL;
    }
    rowIndex++;
    int *result = (int *) malloc(sizeof(int) * rowIndex);
    *returnSize = rowIndex;

    // 计算左面半边的值
    for (int i = 0; i < (rowIndex + 1) / 2; i++) {
        result[i] = combination(rowIndex - 1, i);
    }

    // 将左半部分的值赋值到右面
    for (int i = 0; i < rowIndex / 2; i++) {
        result[rowIndex - 1 - i] = result[i];
    }

    return result;

}

void pprint(int *a, int b) {
    for (int i = 0; i < b; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
}

int main() {

//    printf("%d\n", combination(4, 2));
    int r = 0;
    for (int i = 0; i < 31; i++) {

        int *a = getRow(i, &r);
        pprint(a, r);
    }

}
/Users/zhangguohao/CLionProjects/untitled/cmake-build-debug/untitled
1 
1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
1 5 10 10 5 1 
1 6 15 20 15 6 1 
1 7 21 35 35 21 7 1 
1 8 28 56 70 56 28 8 1 
1 9 36 84 126 126 84 36 9 1 
1 10 45 120 210 252 210 120 45 10 1 
1 11 55 165 330 462 462 330 165 55 11 1 
1 12 66 220 495 792 924 792 495 220 66 12 1 
1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1 
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1 
1 15 105 455 1365 3003 5005 6435 6435 5005 3003 1365 455 105 15 1 
1 16 120 560 1820 4368 8008 11440 12870 11440 8008 4368 1820 560 120 16 1 
1 17 136 680 2380 6188 12376 19448 24310 24310 19448 12376 6188 2380 680 136 17 1 
1 18 153 816 3060 8568 18564 31824 43758 48620 43758 31824 18564 8568 3060 816 153 18 1 
1 19 171 969 3876 11628 27132 50388 75582 92378 92378 75582 50388 27132 11628 3876 969 171 19 1 
1 20 190 1140 4845 15504 38760 77520 125970 167960 184756 167960 125970 77520 38760 15504 4845 1140 190 20 1 
1 21 210 1330 5985 20349 54264 116280 203490 293930 352716 352716 293930 203490 116280 54264 20349 5985 1330 210 21 1 
1 22 231 1540 7315 26334 74613 170544 319770 497420 646646 705432 646646 497420 319770 170544 74613 26334 7315 1540 231 22 1 
1 23 253 1771 8855 33649 100947 245157 490314 817190 1144066 1352078 1352078 1144066 817190 490314 245157 100947 33649 8855 1771 253 23 1 
1 24 276 2024 10626 42504 134596 346104 735471 1307504 1961256 2496144 2704156 2496144 1961256 1307504 735471 346104 134596 42504 10626 2024 276 24 1 
1 25 300 2300 12650 53130 177100 480700 1081575 2042975 3268760 4457400 5200300 5200300 4457400 3268760 2042975 1081575 480700 177100 53130 12650 2300 300 25 1 
1 26 325 2600 14950 65780 230230 657800 1562275 3124550 5311735 7726160 9657700 10400600 9657700 7726160 5311735 3124550 1562275 657800 230230 65780 14950 2600 325 26 1 
1 27 351 2925 17550 80730 296010 888030 2220075 4686825 8436285 13037895 17383860 20058300 20058300 17383860 13037895 8436285 4686825 2220075 888030 296010 80730 17550 2925 351 27 1 
1 28 378 3276 20475 98280 376740 1184040 3108105 6906900 13123110 21474180 30421755 37442160 40116600 37442160 30421755 21474180 13123110 6906900 3108105 1184040 376740 98280 20475 3276 378 28 1 
1 29 406 3654 23751 118755 475020 1560780 4292145 10015005 20030010 34597290 51895935 67863915 77558760 77558760 67863915 51895935 34597290 20030010 10015005 4292145 1560780 475020 118755 23751 3654 406 29 1 
1 30 435 4060 27405 142506 593775 2035800 5852925 14307150 30045015 54627300 86493225 119759850 145422675 155117520 145422675 119759850 86493225 54627300 30045015 14307150 5852925 2035800 593775 142506 27405 4060 435 30 1 

Process finished with exit code 0