【LeetCode】triangle & pascals-triangle i&ii

来源:互联网 发布:国动网络董事长卢杰 编辑:程序博客网 时间:2024/06/07 09:35

题干

triangle

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.

For example, given the following triangle

[     [2],    [3,4],   [6,5,7],  [4,1,8,3]]

The minimum path sum from top to bottom is11(i.e., 2 + 3 + 5 + 1 = 11).

Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

pascals-triangle i

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]]

pascals-triangle ii

Given an index k, return the *k*th row of the Pascal’s triangle.

For example, given k = 3,
Return[1,3,3,1].

Note:
Could you optimize your algorithm to use only O(k) extra space?

三个题都是跟三角形相关的。

问题一,类似于树的深度遍历,得到路径上和最小的路径值。

问题二,杨辉三角,得到固定行数的杨辉三角所有数据。

问题三,杨辉三角,得到第k行的杨辉三角,要求额外的空间开销为o(k)。

数据结构

/** * Definition for singly-linked list. * struct ListNode { *     int val; *     ListNode *next; *     ListNode(int x) : val(x), next(NULL) {} * }; */

解题思路

问题一

类似于树的深度遍历,得到每一条路径的和,找到最小的。但本体的数据结构不是树,没有左右子数的天然联系。于是采用动态规划,设任意结点到叶子节点路径的最小和为sum[i][j]=sum[i][j]+min((sum[i+1][j],sum[i+1][j+1])。于是从下面向上遍历就得到了最终根结点到叶子结点路径的最小和,为sum[0][0]。

问题二

所有数据的杨辉三角用每次上一个的数据进行计算得到即可。

两层循环,第一层i代表行数,第二层j为对每行每个值进行赋值,j=0或者j=i-1的值为triangle[i][0]=triangle[i][i-1]=1,其余triangle[i][j]=triangle[i-1][j-1]+triangle[i-1][j]。

问题三

要求得单一第k行的杨辉三角数据,每一行都是上一行的数据得到的,如果没有空间复杂度要求直接用迭代可解。本体直接用循环解,用一个存储v ectortmp上一层的杨辉三角数据,然后用tmp得到当前层的vecotrtriangle,与上题类似,第i行的第0个和第i-1个数据为1,其余用上一层数据triangle[j]=tmp[j-1]+tmp[j]得到。

参考代码

问题一:

class Solution {public:    int minimumTotal(vector<vector<int> > &triangle) {        if (triangle.size()<=0)            return 0;//无效输入        vector<vector<int>> sum(triangle);//复制一份数据        for(int i=sum.size()-2;i>=0;i--)//行数        {            for(int j=0;j<=i;j++)//每行每个数遍历            {                sum[i][j]=sum[i][j]+(sum[i+1][j]<sum[i+1][j+1])?sum[i+1][j]:sum[i+1][j+1]);//动态规划的表达式            }        }        return sum[0][0];//最终结果    }};

问题二:

class Solution {public:    vector<vector<int> > generate(int numRows) {        vector<vector<int>>triangle=*new vector<vector<int>>();        for(int i=0;i<numRows;i++)        {            vector<int>tmp;            for(int j=0;j<i+1;j++)            {                if (j==0||j==i)//第一个和最后一个数据为1                    tmp.push_back(1);                else                    tmp.push_back(triangle[i-1][j-1]+triangle[i-1][j]);            }            triangle.push_back(tmp);        }        return triangle;    }};

问题三:

方法一:
    class Solution {    public:        vector<int> getRow(int rowIndex) {            vector<int>triangle=*new vector<int>();//当前行数据            vector<int>tmp=*new vector<int>();//存储上一行数据            triangle.push_back(1);//初始化第一行            for(int i=1;i<=rowIndex;++i)            {                for (int j=1; j<i; ++j)                {                    if (j==i)                        triangle.push_back(1);                    else                        triangle[j]=tmp[j-1]+tmp[j];                }                triangle.push_back(1);                tmp=triangle;//把当前行数据存储到tmp以便求下一行            }            return triangle;        }    };
方法二:
    class Solution {    public:    vector<int> getRow(int rowIndex) {        vector<int> triangle(rowIndex+1, 0);        triangle[0] = 1; //初始化第一个值        for(int i=1; i<rowIndex+1; i++)             for(int j=i; j>=1; j--)//每行从后向前遍历                triangle[j] += triangle[j-1];                 return triangle;        }            };

方法讨论

三个题主要都是动态规划,写出每行之间的关系即可。

易错点

对于vector数据的输入

vector动态分配,没有分配值的vector元素是不可以用[][]的方式进行访问,也就是说,赋值的时候要用push_back()接口来进行赋值,而不能直接按照数组的赋值方式,因为未赋值,这样访问不合法。

数据覆盖问题

在问题三中,也可以不开辟储存上一行的空间。但注意数据不要覆盖掉。由于triangle[j]=triangle[j-1]+triangle[j],故从后往前遍历就会避免覆盖数据的情况。

边界条件

1.动态规划的边界条件,第一行或者第一个值要提前单独赋值,要不然无法迭代出后面的值。

2.对于杨辉三角每一行的第一个或者最后一个字符不在循环内。

0 0
原创粉丝点击