LeetCode - 0118.杨辉三角 & 0119.杨辉三角II

2022-04-27

0118.杨辉三角 和 0119.杨辉三角II 这两个题目都是在解决同一个问题,所以放在一起解答。

题目1

来源:0118.杨辉三角

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。

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

pascalTriangle

难度:简单

示例1

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

示例2

输入: numRows = 1
输出: [[1]]

提示

  • 1 <= numRows <= 30

分析

从示意图可以很清楚地看出杨辉三角是如何生成的。 从第三行开始,对于每一行,除去两边都是 1 外,其余元素都是他上一行相邻的元素从左到右依次相加之和。

我们已知第 1 行和第 2 行作为基本情况,对于第 n 行元素,都可以由第 n - 1 行的元素按上述规律生成,所以很明显,这是一个 动态规划 的问题。

题目要求输出前 numRows 行,我们就从第 0 行开始,按规律依次生成第 i 行,直到第 numRows - 1 行为止即可。

解答

public class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> dp = new ArrayList<>();

        for (int i = 0; i < numRows; i++) {
            // 生成当前第 i 行
            List<Integer> row = new ArrayList<>();
            for (int j = 0; j <= i; j++) {
                if (j == 0 || j == i) { // 每行的左右两侧元素都是 1
                    row.add(1);
                } else {
                    // 拿到上一行对应位置的元素,相加
                    List<Integer> prevRow = dp.get(i - 1);
                    row.add(prevRow.get(j - 1) + prevRow.get(j));
                }
            }
            dp.add(row);
        }

        return dp;
    }
}

0119.杨辉三角II 也是一道有关生成杨辉三角的题目,只不过他要求输出第 n 行的元素,而且要求 O(n) 的空间复杂度,我们来看一下。

题目2

来源:0119.杨辉三角II

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

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

pascalTriangle

难度:简单

示例1

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

示例2

输入: rowIndex = 0
输出: [1]

示例3

输入: rowIndex = 1
输出: [1,1]

提示

  • 1 <= numIndex <= 33

进阶

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

分析

在做 动态规划 的题目时,很多时候要求我们输出第 n 种情况,比如斐波那契数列问题要求输出第 n 个元素。

我们一般会用一个一维或二维数组(视问题而定)来存储动态规划问题计算过程的中间结果。像这种只要求输出第 n 种情况的题目,我们可以想办法把这个存储中间结果的数组省略掉。

我们只要构造出第 n 种情况即可。解法依旧是从第 0 行开始,生成第 1 行元素,生成第 2 行元素……直到第 n 行。

解答

public class Solution {
    public List<Integer> getRow(int rowIndex) {
        // 最终要输出的这一行,并把他初始化
        List<Integer> row = new ArrayList<>();
        for (int i = 0; i <= rowIndex; i++) {
            row.add(1);
        }

        // i 从 0 到 n,依次生成第 i 行的元素
        for (int i = 0; i <= rowIndex; i++) {
            // prev 用于记录上一行对应位置元素的值
            int prev = row.get(0);
            for (int j = 0; j <= i; j++) {
                if (j == 0 || j == i) { // 每行两侧元素的值为 1
                    row.set(j, 1);
                } else {
                    // 计算上一行对应位置两个元素的和
                    int temp = row.get(j);
                    row.set(j, prev + row.get(j));
                    prev = temp;
                }
            }
        }

        return row;
    }
}

我们用了一个长度为 n 的数组(列表),所以满足 O(n) 的空间复杂度。

LeetCode

Jeff Liu

LeetCode - 0070.爬楼梯