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 9 36 84 126 126 84 36 9 1
第一种使用递归思想
我们把三角右对齐(以高度为6的杨辉三角为例)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
不难看出,从第三行开始,除了每一行的第一个元素与最后一个元素为1,其他的元素为上一行的前一列元素+上一行的同列元素
public class YangHuiTriangle {
public static void main(String[] args) {
int n = 10;
for (int i = 0; i < n; i++) {
printBlank(n,i);
for (int j = 0; j <= i; j++) {
System.out.printf("%-4d", getElement(i,j));
}
System.out.println();
}
}
private static void printBlank(int n, int i) {
int num = (n-1-i)*2;
for (int j = 0; j < num; j++) {
System.out.print(" ");
}
}
private static int getElement(int i, int j) {
if (j == 0 || i == j) {
return 1;
}
return getElement(i - 1, j - 1) + getElement(i - 1, j);
}
}
第二种,使用数组记录
1)二维数组记录
private static void print1(int n) {
int[][] cache = new int[n][];
for (int i = 0; i < cache.length; i++) {
cache[i] = new int[i + 1];
Arrays.fill(cache[i], -1);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
System.out.printf("%-4d", getElement1(i, j, cache));
}
System.out.println();
}
}
/**
* 使用二维数组记忆法
*
* @param i 行数
* @param j 列数
* @param cache 缓存数组
* @return
*/
private static int getElement1(int i, int j, int[][] cache) {
if (j == 0 || i == j) {
cache[i][j] = 1;
}
if (cache[i][j] == -1) {
int x = getElement1(i - 1, j - 1, cache);
int y = getElement1(i - 1, j, cache);
cache[i][j] = x + y;
}
return cache[i][j];
}
由于每一行的元素个数不相等所以为了节省空间,不要初始化长为n*n的数组而是动态的去赋予每一行的长度,不难看出每一行的元素个数与其是第几行密切相关,也是就 元素个数=行数,当然数组下标由0开始
所以有了
int[][] cache = new int[n][];
for (int i = 0; i < cache.length; i++) {
cache[i] = new int[i + 1];
Arrays.fill(cache[i], -1);//数组内元素全部填充为-1(当然也可以不用这样因为初始值为0)
}
进入getElement1()方法,如果是第一个元素和最后一个元素,那么将此位置的值赋为1,不是的话就去计算它上一行的上一列元素赋给变量x,上一行同列元素赋给变量y,再将两变量之和赋给数次此索引,也就是cache[i][j]=x+y,在返回此值供print1()方法打印
2)一维数组记录(动态规划)
/**
* @param j 列数
* @param cache 一维缓存数组
* @return
*/
private static int getElement2(int j, int[] cache) {
return cache[j];
}
/**
* @param i 行数,用于创建此行的元素
* @param cache 一维缓存数组
*/
private static void createRow(int i, int[] cache) {
//我们以求高度为6的杨辉三角为例:
//除了第一行也就是i=0时我们需要自己将次数组创建为{1,0,0,0,0,0}
/*if (i == 0) {
cache[0] = 1;
return;
}
第二次 传进来的cache={1,0,0,0,0,0}经历下方的循环
for (int j =1;j>=0;j--){
*(j == i)=1*
if (j == i || j == 0) {
cache[j] = 1;
continue;
}
}
for (int j =0;j>=0;j--){
*j=0*
if (j == i || j == 0) {
cache[j] = 1;
continue;
}
}
可得现在的cache{1,1,0,0,0,0}
第三次传进来的cache={1,1,0,0,0,0}经历下方的循环
for (int j =2;j>=0;j--){
*(j == i)=2*
if (j == i || j == 0) {
cache[j] = 1;
continue;
}
}
for (int j =1;j>=0;j--){
cache[j] = cache[j - 1] + cache[j]=2;
}
for (int j = 0; j >= 0; j--) {
*j=0*
if (j == i || j == 0) {
cache[j] = 1;
continue;
}
}
可得cache为{1,2,1,0,0,0}
第四次传进来的cache={1,2,1,0,0,0}经历下方的循环
for (int j =3;j>=0;j--){
*(j == i)=3*
if (j == i || j == 0) {
cache[j] = 1;
continue;
}
}
for (int j =2;j>=0;j--){
cache[j] = cache[j - 1] + cache[j]=3;
}
for (int j = 1; j >= 0; j--) {
cache[j] = cache[j - 1] + cache[j]=3;
}
可得cache为{1,3,3,1,0,0}
同理可得第六次cache为{1,5,10,10,5,1}*/
for (int j = i; j >= 0; j--) {
if (j == i || j == 0) {
cache[j] = 1;
continue;
}
cache[j] = cache[j - 1] + cache[j];
}
}
private static void print2(int n) {
int[] cache = new int[n];
for (int i = 0; i < n; i++) {
createRow(i,cache);
for (int j = 0; j <= i; j++) {
System.out.printf("%-4d",getElement2(j, cache));
}
System.out.println();
}
}
经过createRow()方法创建了第i+1行的元素,直接遍历输出即可,也就是print2()方法。