前言
杨辉三角,也叫贾宪三角,帕斯卡三角。最早出现于北宋时期,贾宪首先使用“贾宪三角”进行高次开方运算。后来南宋杨辉进行辑录出书,帕斯卡是迟于杨辉三四百年才发现这一规律,叫法上看个人习惯,我习惯称之为杨辉三角。
杨辉三角前几行示图:
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
每一行除了首尾元素,其他元素都是其上方两元素之和
第 n 行有 n 个元素(行号从 1 开始)
每行元素都是对称的,逐渐变大再逐渐变小
很明显,杨辉三角形每一层的数字跟二项式系数有很亲密的关系。
引题
这个题最讨厌的不仅是要输出前 n 行,还要塞进一个 list 数组里面。毕竟题目是以算法的形式呈现,不能直接打印输出。
思路: 每一行除了首尾元素,其他元素都是其上方两元素之和,抓住这一点就好办了。然后利用 for 循环造出每一行的数字。
代码:
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> triangle = new ArrayList<>();
for (int i = 0; i < numRows; i++) {
List<Integer> list = new ArrayList<>();
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i) {
list.add(1);
} else {
list.add(triangle.get(i - 1).get(j - 1) + triangle.get(i - 1).get(j));
}
}
triangle.add(list);
}
return triangle;
}
}
上面最终返回的结果是一个数组,要想真的输出一个等腰三角形的杨辉三角该怎么办,请看下面讲解。
打印杨辉三角(等腰三角形)
有了上面的讲解,输出杨辉三角的每一行的值是比较简单的,输出整个杨辉三角并且以等腰三角形的形式输出就比较难了,因为你要控制空格数。
代码1:
1 public class YanghuiTriangleExample {
2
3 public static void main(String[] args) {
4 int rows = 10;
5
6 for(int i =0;i<rows;i++) {
7 int number = 1;
8 //打印空格字符串
9 System.out.format("%"+(rows-i)*2+"s","");
10 for(int j=0;j<=i;j++) {
11 System.out.format("%4d",number);
12 number = number * (i - j) / (j + 1);
13 }
14 System.out.println();
15 }
16 }
17 }
/**
* 获取杨辉三角的指定行
* 直接使用组合公式C(n,i) = n!/(i!*(n-i)!)
* 则第(i+1)项是第i项的倍数=(n-i)/(i+1);
*/
原文:https://www.cnblogs.com/JumperMan/p/6759422.html
上面这个代码不能说看不懂吧,那是看的一脸懵逼。后来才发现是涉及到数学知识,不明白的请看里面的注释。
下面搞一点通俗易懂的代码
代码2:
边生成边打印
public static void main(String[] args) {
//假定输出前5行
int row = 5;
int[][] array = new int[row][row];
for (int i = 0; i < row; i++) {
for (int j = 0; j < row - i; j++) {
System.out.print(" ");
}
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i) {
array[i][j] = 1;
} else {
array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
}
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
先生成数组,再全部打印
public static void main(String[] args) {
//假定输出前6行
int row = 6;
int[][] array = new int[row][row];
for (int i = 0; i < row; i++) {
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i) {
array[i][j] = 1;
} else {
array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
}
}
}
// 等腰输出处理
for (int i = 0; i < row; i++) {
int num = row - i;// 这里的num只是控制与左边界限的距离
for (int j = 0; j <= num; j++) {
System.out.print(" ");
}
for (int k = 0; k <= i; k++) {
System.out.print(array[i][k] + " ");
}
System.out.println();
}
}
上面代码也比较简单,把握好循环次数就好,包括那些空格的输出。
打印杨辉三角(直角三角形)
搞明白等腰的打印原理,这个就更好理解了。原理都是一样的,直接上代码。
代码:
public static void main(String[] args) {
//假定输出前6行
int row = 6;
int[][] array = new int[row][row];
for (int i = 0; i < row; i++) {
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i) {
array[i][j] = 1;
} else {
array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
}
}
}
// 等腰输出处理
for (int i = 0; i < row; i++) {
for (int k = 0; k <= i; k++) {
System.out.print(array[i][k] + " ");
}
System.out.println();
}
}
打印杨辉三角第n行
没啥可说的,原理都一样,思路也一样。注意看清楚示例就行了,因为题目中是从第 0 行算起。
个人代码:
class Solution {
public List<Integer> getRow(int rowIndex) {
List<Integer> list = new ArrayList<>();
int[][] array = new int[rowIndex+1][rowIndex+1];
for (int i = 0; i < rowIndex+1; i++) {
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i) {
array[i][j] = 1;
} else {
array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
}
}
}
for (Integer i : array[rowIndex]) {
list.add(i);
}
return list;
}
}
优化:
因为我们每次用到的都是上一行的数据,所以可以使用滚动数组的思想优化数组空间,滚动数组只用存储一行数据,并且实时更新
class Solution {
public List<Integer> getRow(int rowIndex) {
List<Integer> array = new ArrayList<>();
for (int i = 0; i <= rowIndex; ++i) {
List<Integer> curArray = new ArrayList<>();
for (int j = 0; j <= i; ++j) {
if (j == 0 || j == i) {
curArray.add(1);
} else {
curArray.add(array.get(j - 1) + array.get(j));
}
}
array = curArray;
}
return array;
}
}
高级做法:
public List<Integer> getRow(int rowIndex) {
List<Integer> res = new ArrayList<>(rowIndex + 1);
long cur = 1;
for (int i = 0; i <= rowIndex; i++) {
res.add((int) cur);
cur = cur * (rowIndex-i)/(i+1);
}
return res;
}
这里可能有点不好理解,主要就是运用了组合数的数学知识
* 直接使用组合公式C(n,i) = n!/(i!*(n-i)!)
* 则第(i+1)项是第i项的倍数=(n-i)/(i+1);
写在最后
到此,杨辉三角的相关内容就全部讲完了,难度不大,重点是掌握思路方法,这样才能灵活运用。