zoukankan      html  css  js  c++  java
  • [LeetCode]15. Pascal's Triangle杨辉三角

    Given numRows, generate the first numRows of Pascal's triangle.

    For example, given numRows = 5,
    Return

    [
         [1],
        [1,1],
       [1,2,1],
      [1,3,3,1],
     [1,4,6,4,1]
    ]

    杨辉三角主要有下列五条性质:

    1. 杨辉三角以正整数构成,数字左右对称,每行由1开始逐渐变大,然后变小,回到1。
    2. n行的数字个数为n个。
    3. n行的第k个数字为组合数C_{n-1}^{k-1}
    4. n行数字和为2^{n-1}
    5. 除每行最左侧与最右侧的数字以外,每个数字等于它的左上方与右上方两个数字之和(也就是说,第n行第k个数字等于第n-1行的第k-1个数字与第k个数字的和)。这是因为有组合恒等式:C_{n}^{i}=C_{n-1}^{i-1}+C_{n-1}^{i}

    解法1:根据杨辉三角的构造方法直接构造。

    class Solution {
    public:
        vector<vector<int>> generate(int numRows) {
            vector< vector<int> > res;
            for(int i = 0; i < numRows; i++)
            {
                vector<int> row(i + 1, 1);
                for(int j = 1; j < i; j++)
                    row[j] = res[i - 1][j - 1] + res[i - 1][j];
                res.push_back(row);
            }
            return res;
        }
    };

    解法2:杨辉三角的每一行的各元素即是组合数C(m,n),其中n表示第几行,m=0,1,...,n,使用公式C(m,n)=n!/m!/(n-m)!

    class Solution {
    public:
        vector<vector<int>> generate(int numRows) {
            vector< vector<int> > res;
            for(int i = 0; i < numRows; i++)
            {
                vector<int> row(i + 1, 1);
                for(int j = 0; j <= i; j++)
                    row[j] = fact(i) / fact(j) / fact(i - j);
                res.push_back(row);
            }
            return res;
        }
    private:
        long long fact(int n)
        {
            if(n <= 1)
                return 1;
            long long f = 1, res;
            for(int i = 2; i <= n; i++)
            {
                res = f * i;
                f = res;
            }
            return res;
        }
    };

    注意这个不能通过全部测试,原因在于numRows比较大时计算阶乘会溢出。考虑组合数计算的另外的公式C(m,n)=C(m-1,n-1)+C(m,n-1)可以改进:

    class Solution {
    public:
        vector<vector<int>> generate(int numRows) {
            vector< vector<int> > res;
            for(int i = 0; i < numRows; i++)
            {
                vector<int> row = getRow(i);
                res.push_back(row);
            }
            return res;
        }
    private:
        vector<int> getRow(int rowIndex) {
            vector<int> row;
            if (rowIndex < 0) 
                return row;
    
            row.assign(rowIndex + 1, 0);
            for (int i = 0; i <= rowIndex; ++i) 
            {
                if (i == 0) 
                {
                    row[0] = 1;
                    continue;
                }
                for (int j = rowIndex; j >= 1; --j) 
                    row[j] = row[j] + row[j - 1];
            }
            return row;
        }
    };

    这个方法效率比较差,因为为了计算第row行的数据,首先将第1行到第row-1行的所有数据都计算了一遍。

  • 相关阅读:
    VSCode中按ESLint规则格式化Javascript代码
    VSCode设置资源管理器字体大小
    Windows下利用安装压缩包安装MySQL
    Windows部署Apache 2.4.46及PHP 8.0.3
    npm设置国内镜像
    IDEA运行Tomcat输出信息乱码
    深入理解jvm虚拟机读书笔记-Java内存区域与内存溢出异常
    Navicat Premium
    mysql安装
    ElasticSearch 基础
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/4859217.html
Copyright © 2011-2022 走看看