[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行的所有数据都计算了一遍。

posted @ 2015-10-07 19:40  AprilCheny  阅读(191)  评论(0编辑  收藏  举报