杨辉三角经典算法大总结(Java版)

前言

杨辉三角,也叫贾宪三角,帕斯卡三角。最早出现于北宋时期,贾宪首先使用“贾宪三角”进行高次开方运算。后来南宋杨辉进行辑录出书,帕斯卡是迟于杨辉三四百年才发现这一规律,叫法上看个人习惯,我习惯称之为杨辉三角。

杨辉三角前几行示图:
      
        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);

写在最后

到此,杨辉三角的相关内容就全部讲完了,难度不大,重点是掌握思路方法,这样才能灵活运用。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值