🚩传送门:牛客题目
力扣题目

题目

给定一个非负索引 [NC]246. 杨辉三角 II - 图1,其中 [NC]246. 杨辉三角 II - 图2,返回杨辉三角的第 [NC]246. 杨辉三角 II - 图3 行。
PascalTriangleAnimated2.gif
在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

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

进阶:
你可以优化你的算法到 [NC]246. 杨辉三角 II - 图5 空间复杂度吗?

解题思路:递推

根据杨辉三角性质,第 [NC]246. 杨辉三角 II - 图6 行的第 [NC]246. 杨辉三角 II - 图7 个数等于第 [NC]246. 杨辉三角 II - 图8 行的第 [NC]246. 杨辉三角 II - 图9 个数和第 [NC]246. 杨辉三角 II - 图10 个数之和。即 [NC]246. 杨辉三角 II - 图11,可以线性递推

初始版本代码

  1. class Solution {
  2. public List<Integer> getRow(int rowIndex) {
  3. List<List<Integer>> C = new ArrayList<List<Integer>>();
  4. for (int i = 0; i <= rowIndex; ++i) {
  5. List<Integer> row = new ArrayList<Integer>();
  6. for (int j = 0; j <= i; ++j) {
  7. if (j == 0 || j == i) {
  8. row.add(1);
  9. } else {
  10. row.add(C.get(i - 1).get(j - 1) + C.get(i - 1).get(j));
  11. }
  12. }
  13. C.add(row);
  14. }
  15. return C.get(rowIndex);
  16. }
  17. }

优化版本代码

注意到对第 [NC]246. 杨辉三角 II - 图12 行的计算仅用到了第 [NC]246. 杨辉三角 II - 图13 行的数据,因此可以使用滚动数组的思想优化空间复杂度。

  1. class Solution {
  2. public List<Integer> getRow(int rowIndex) {
  3. List<Integer> pre = new ArrayList<Integer>();
  4. for (int i = 0; i <= rowIndex; ++i) {
  5. List<Integer> cur = new ArrayList<Integer>();
  6. for (int j = 0; j <= i; ++j) {
  7. if (j == 0 || j == i) {
  8. cur.add(1);
  9. } else {
  10. cur.add(pre.get(j - 1) + pre.get(j));
  11. }
  12. }
  13. pre = cur;
  14. }
  15. return pre;
  16. }
  17. }

更优版本代码

能否只用一个数组呢?
递推式 [NC]246. 杨辉三角 II - 图14 表明,当前行第 [NC]246. 杨辉三角 II - 图15 项的计算只与上一行第 [NC]246. 杨辉三角 II - 图16 项及第 [NC]246. 杨辉三角 II - 图17 项有关。

因此我们可以倒着计算当前行,这样计算到第 [NC]246. 杨辉三角 II - 图18 项时,第 [NC]246. 杨辉三角 II - 图19 项仍然是上一行的值。(不会发生覆盖

复杂度分析

时间复杂度:[NC]246. 杨辉三角 II - 图20

空间复杂度:[NC]246. 杨辉三角 II - 图21 。不考虑返回值的空间占用。

  1. class Solution {
  2. public List<Integer> getRow(int rowIndex) {
  3. List<Integer> row = new ArrayList<Integer>();
  4. row.add(1);
  5. for (int i = 1; i <= rowIndex; ++i) {
  6. row.add(0);
  7. for (int j = i; j > 0; --j) {
  8. row.set(j, row.get(j) + row.get(j - 1));
  9. }
  10. }
  11. return row;
  12. }
  13. }

解题思路:线性递推

由组合数公式 [NC]246. 杨辉三角 II - 图22,可以得到同一行的相邻组合数的关系 [NC]246. 杨辉三角 II - 图23,由于[NC]246. 杨辉三角 II - 图24,利用上述公式我们可以在线性时间计算出第 [NC]246. 杨辉三角 II - 图25 行的所有组合数。

复杂度分析

时间复杂度:[NC]246. 杨辉三角 II - 图26

空间复杂度:[NC]246. 杨辉三角 II - 图27 。不考虑返回值的空间占用。

我的代码

  1. class Solution {
  2. public List<Integer> getRow(int rowIndex) {
  3. List<Integer> row = new ArrayList<Integer>();
  4. row.add(1);
  5. for (int i = 1; i <= rowIndex; ++i) {
  6. row.add((int) ((long) row.get(i - 1) * (rowIndex - i + 1) / i));
  7. }
  8. return row;
  9. }
  10. }