【力扣算法】118-杨辉三角

题目

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

【力扣算法】118-杨辉三角_第1张图片

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

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/pascals-triangle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

方法:动态规划

思路

如果能够知道一行杨辉三角,我们就可以根据每对相邻的值轻松地计算出它的下一行。

算法

虽然这一算法非常简单,但用于构造杨辉三角的迭代方法可以归类为动态规划,因为我们需要基于前一行来构造每一行。

首先,我们会生成整个 triangle 列表,三角形的每一行都以子列表的形式存储。然后,我们会检查行数为 00 的特殊情况,否则我们会返回 [ 1 ] [1] [1]。如果 n u m R o w s > 0 numRows > 0 numRows>0,那么我们用 [ 1 ] [1] [1] 作为第一行来初始化 triangle with [ 1 ] [1] [1],并按如下方式继续填充:

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

        // First base case; if user requests zero rows, they get zero rows.
        if (numRows == 0) {
            return triangle;
        }
    
        // Second base case; first row is always [1].
        triangle.add(new ArrayList<>());
        triangle.get(0).add(1);
    
        for (int rowNum = 1; rowNum < numRows; rowNum++) {
            List<Integer> row = new ArrayList<>();
            List<Integer> prevRow = triangle.get(rowNum-1);
    
            // The first row element is always 1.
            row.add(1);
    
            // Each triangle element (other than the first and last of each row)
            // is equal to the sum of the elements above-and-to-the-left and
            // above-and-to-the-right.
            for (int j = 1; j < rowNum; j++) {
                row.add(prevRow.get(j-1) + prevRow.get(j));
            }
    
            // The last row element is always 1.
            row.add(1);
    
            triangle.add(row);
        }
    
        return triangle;
    }
}

复杂度分析

时间复杂度: O ( n u m R o w s 2 ) O(numRows^2) O(numRows2)

虽然更新 triangle 中的每个值都是在常量时间内发生的, 但它会被执行 O ( n u m R o w s 2 ) O(numRows^2) O(numRows2) 次。想要了解原因,就需要考虑总共有多少 次循环迭代。很明显外层循环需要运行 n u m R o w s numRows numRows 次,但在外层循环的每次迭代中,内层 循环要运行 r o w N u m rowNum rowNum 次。因此,triangle 发生的更新总数为 1 + 2 + 3 + … + n u m R o w s 1 + 2 + 3 + \ldots + numRows 1+2+3++numRows,根据高斯公式 有

n u m R o w s ( n u m R o w s + 1 ) 2 = n u m R o w s 2 + n u m R o w s 2 = n u m R o w s 2 2 + n u m R o w s 2 = O ( n u m R o w s 2 ) \begin{aligned} \frac{numRows(numRows+1)}{2} &= \frac{numRows^2 + numRows}{2} \\ &= \frac{numRows^2}{2} + \frac{numRows}{2} \\ &= O(numRows^2) \end{aligned} 2numRows(numRows+1)=2numRows2+numRows=2numRows2+2numRows=O(numRows2)

空间复杂度: O ( n u m R o w s 2 ) O(numRows^2) O(numRows2)

因为我们需要存储我们在 triangle 中更新的每个数字, 所以空间需求与时间复杂度相同。

作者:LeetCode
链接:https://leetcode-cn.com/problems/two-sum/solution/yang-hui-san-jiao-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

感想

执行用时 :2 ms, 在所有 Java 提交中击败了28.69%的用户

内存消耗 :33.6 MB, 在所有 Java 提交中击败了41.66%的用户

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> res = new LinkedList<>();
        for(int i = 0;i<numRows;i++){
            LinkedList<Integer> list = new LinkedList<>();
            //System.out.println("i-1:"+(i-1)+",i/2-1:"+(i/2-1)+",i/2:"+(i/2));
            if(i>1 && i%2==0) list.add(res.get(i-1).get(i/2-1)+res.get(i-1).get(i/2));
            for(int j=(i-1)/2;j>0;j--){
                int sum = res.get(i-1).get(j-1)+res.get(i-1).get(j);
                list.addFirst(sum);
                list.add(sum);
            }
            list.addFirst(1);
            if(i!=0)list.add(1);
            //System.out.println(list);
            res.add(list);
        }
        return res;
    }
}

你可能感兴趣的:(java)