zoukankan      html  css  js  c++  java
  • 也谈杨辉三角形

    很久没更新博客了,来篇水的。今天看见有位兄弟写了杨辉三角形,记得以前自己也研究过,索性也发一篇,欢迎讨论。

    来历

    杨辉三角形也叫贾宪三角形,西方叫帕斯卡三角形,其实就是各阶二项式系数排列起来构成的三角形,如下。每行的数字实际上是(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 ;
    }
    }

    输出如下,因为处理了空格,所以更美观一点。

    Happy Coding!!!

    == THE END ==

    作者:zdd
    出处:http://www.cnblogs.com/graphics/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    2星|《丰田一页纸极简思考法》:僵化、不易扩展、修改,价值不大
    4星|《亿万》:FBI大战华尔街对冲基金大鳄
    3星|《CMO到底能干多久?》:CEO必须决定供公司需要哪类CMO
    中老年创业成功率更高,美国投资人的创业指南:4星|《烧掉你的商业计划书》
    3星|《科技投资新时代》:TMT行业资讯汇编
    2星|史蒂芬·平克《风格感觉》:英语写作指导,不适合外行阅读
    3星|《故事课1》:7个步骤+36种情节+悬念,作者没有拿得出手的故事作品
    2.5星|《数字货币:世界为我疯狂》:5年来《商业周刊》的区块链与比特币相关的文章16篇
    2.5星|《哈佛商学院管理与MBA案例全书》:书名太唬人了,依据中文经管书汇编整理而成
    3.5星|《第一本经济学》:通俗、可信的经济学入门
  • 原文地址:https://www.cnblogs.com/graphics/p/2103117.html
Copyright © 2011-2022 走看看