杨辉三角问题

杨辉三角形也叫贾宪三角形,西方叫帕斯卡三角形,其实就是各阶二项式系数排列起来构成的三角形,如下。每行的数字实际上是(a + b) ^ n展开后的结果。

          1 
         1 1 
        1 2 1 
       1 3 3 1 
      1 4 6 4 1

历史上发现这个三角形的人很多,这里介绍几个主要的,北宋人贾宪约1050年首先使用“贾宪三角”进行高次开方运算。杨辉,字谦光,南宋时期杭州人。在他1261年所著的《详解九章算法》一书中,辑录了如上所示的三角形数表,称之为“开方作法本源”图。欧洲直到1623年以后,法国数学家帕斯卡在13岁时发现了“帕斯卡三角”。

编程输出杨辉三角形

方法一

使用二维数组计算并存储各行数字然后输出,如果不考虑每行左侧空格的话,上面的三角形可以写成如下形式

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

根据观察我们发现,第一列和对角线上的数字都是1,其他数字则是其左上方数字和正上方数字之和,如下图,其中数字1被标记成红色,因为1是我们预先设置好的,图中的白色数字为合成数字,合成数字是由1或者其他已经存在的数字相加而成的。比如数字2是由其上方的1和左上方的1相加而成,第一个3是由其上方的2和左上方的1相加而成。

设p是存储数字的二维数组,设i和j分别表示p的行号和列号,则有

  • 如果j == 0 或 j == i,则p[i][j] = 1 ;
  • 否则,p[i][j] = p[i - 1][j] + p[i - 1][j - 1] ;

有了上面的分析,写代码就不再是难事了。

复制代码
  
  
// 打印杨辉三角形,参数n是层数 void YanghuiTriangle( int n) { // 定义二维数组并初始化 int ** p = new int * [n] ; for ( int i = 0 ; i < n; ++ i) { p[i] = new int [n] ; for ( int j = 0 ; j < n; ++ j) p[i][j] = 0 ; } // 填充并输出 for ( int i = 0 ; i < n; ++ i) { for ( int j = 0 ; j <= i; ++ j) { // 第一列和对角线列的元素置1 if (j == 0 || j == i) p[i][j] = 1 ; // 其他元素是其上方元素和左上方元素之和 else p[i][j] = p[i - 1 ][j] + p[i - 1 ][j - 1 ] ; cout << p[i][j] << " " ; } cout << endl ; } }
复制代码

输出如下

方法二

方法一的优点是直观,代码好写,但是缺点是如果层数n很大的话,那么将需要很大的存储空间(n * n),而这么大的空间中有一半被浪费掉了。下面这个方法使用一维数组实现,空间上只要n即可。思路是逐行计算并输出,举个例子,假设我们要输出5行(n = 5),我们先计算并输出第一行,然后计算并输出第二行,...,最后是第五行,因为每行的数字个数不超过行数n,所以一个含有n个元素的一维数组就可以胜任了,只不过这个一维数组中的数字是不断变化的(除了第一个元素),我们用新增的元素覆盖掉了原来的元素。下图展示了这个一维数组的变化过程。其中红色字数字表示每次迭代新增的数字。可见这种方法中第一列数字1始终保持不变。

1 首先定义一个含有n个元素的一维数组,且第一个元素初始化为1,其他元素初始化为0

2 对于每一行的计算,除了第一元素之外,其他所有元素都由其本身的值加上其前一个值构成,注意,计算的方向是从后向前,如果从前向后的话,元素本来的值将被覆盖。

代码如下

复制代码
  
  
// 打印杨辉三角形,参数n是层数 void YanghuiTriangle( int n) { // 定义一个一维数组 int * a = new int [n] ; for ( int i = 0 ; i < n; ++ i) a[i] = 0 ; a[ 0 ] = 1 ; for ( int i = 0 ; i < n; ++ i) { // 计算当前行的数字,注意要从后向前计算,否则会覆盖以前的值 for ( int j = i; j > 0 ; -- j) a[j] += a[j - 1 ]; // 打印空格 for ( int j = 0 ; j < n - i; ++ j) cout << " " ; // 打印数字 for ( int j = 0 ; j < i + 1 ; ++ j) cout << a[j] << " " ; cout << endl ; } }
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值