leetcode#118 Pascal’s Triangle

Given numRows, generate the first numRows of Pascal’s triangle.

For example, given numRows = 5,
Return

1
2
3
4
5
6
7
8
>[
> [1],
> [1,1],
> [1,2,1],
> [1,3,3,1],
> [1,4,6,4,1]
>]
>

解释

Pascal’s Triangle,帕斯卡三角形,又称杨辉三角。

给定一个整数,要求返回以该整数作为三角形层数的杨辉三角。

我的解法

虽然题目要求返回一个以链表作为对象的链表容器,但是仍然可以将其转换为数组问题——利用数组索引查询的便利性,可以很容易(其实我还是想了一会……)地构造出一个二维数组,然后再将二维数组转换成链表,返回即可。

接下来,分析一下杨辉三角,可以看到:

  • 第 i 层,有 i 个元素;
  • 每一层的元素值都是对称分布的,且首尾两个元素值一直都是1;
  • 除了首尾两个元素值外,每一层的第 j 个元素值都等于上一层的第 j 个元素值加上第 (j-1) 个元素值(如果有的话)。

所以,只要在计算第 i 层数组的时候,保留有上一层的数组,就可以通过数组索引查找的方式,很简单地完成新数组元素的计算和填充。每完成一层数组的填充,就可以将其放入全局的二维数组中。最后再将二维数组转换成链表即可。

时间复杂度为O(N2),1ms。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> pascal = new ArrayList<List<Integer>>();
int[][] pascalArray = new int[numRows][];
if(numRows == 0) return pascal;
else {
int[] preArray = {0};
for(int i = 1; i <= numRows; i++) {
int[] layer = new int[i];
layer[0] = 1;
layer[i - 1] = 1;
for(int j = 1; j < (i+1)/2; j++) { // 每次求一半即可,另一半是对称的
layer[j] = preArray[j - 1] + preArray[j];
layer[i-1-j] = layer[j];
}
preArray = layer;
pascalArray[i- 1] = layer;
}
// List list = Arrays.asList(pascalArray);
// 很神奇,需要强制转换成List,再赋值给pascal才不会有误
pascal = (List)Arrays.asList(pascalArray);
return pascal;
}
}
}

大神解法

使用子链表+动态规划

解题思想都是一样的,但是由于无法像数组一样快速地通过索引定位元素值,所以需要对子链表的所有节点进行赋值(即使存在对称)。

优点是,每完成一个子链表,就可以直接作为对象加入最终的链表容器(也算作是动态规划吧),省去了数组转链表的一个操作。

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

总结

本题还是比较灵活的,既可以使用数组的方式解决,也可以使用链表。而且在使用数组的时候,对数组索引灵活运用的考察还是比较关注的。