您的位置:首页 > 其它

【LeetCode】triangle & pascals-triangle i&ii

2017-05-08 15:47 399 查看

题干

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.对于杨辉三角每一行的第一个或者最后一个字符不在循环内。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode