①杨辉三角
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
在杨辉三角中,每个数是它左上方和右上方的数的和。
示例:
输入: 5
输出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
杨辉三角的性质:
- 杨辉三角以正整数构成,数字左右对称,每行由1开始逐渐变大,然后变小,回到1。
- 第行的数字个数为个。
- 第行的第个数字为组合数。
- 第行数字和为。
- 除每行最左侧与最右侧的数字以外,每个数字等于它的左上方与右上方两个数字之和(也就是说,第行第个数字等于第行的第个数字与第个数字的和)。这是因为有组合恒等式:。可用此性质写出整个杨辉三角形。
1.用两层循环,利用杨辉三角的性质(每一层除首尾外其他元素都为上一层的两个元素之和,即a[i][j] = a[i-1][j-1] + a[i - 1][j]),可以将其类比为二维数组,逐行插入数据得出结果:
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> vec(numRows); ///定义一个目标容器保存结果
if(numRows <= 0) return vec; //如果传入的numRows小于等于0,则返回空容器
for (int i = 0; i < numRows; ++i) //外层循环,对所有行进行操作
{
vec[i].push_back(1); //将每一行的首元素置1
for (int j = 0; j < i; ++j) //内层循环,对行内每个元素操作
{
f (i > j && j != 0) //如果不是首元素并且j不等于0(等于0则j-1越界),将上层两个元素之后插入该层位置
vec[i].push_back(vec[i-1][j] + vec[i - 1][j-1]);
}
if (i > 0)
vec[i].push_back(1); //如果不是第一行,则添加尾元素
}
return vec;
}
};
杨辉三角Ⅱ
给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。
在杨辉三角中,每个数是它左上方和右上方的数的和。
示例:
输入: 3
输出: [1,3,3,1]
进阶:
你可以优化你的算法到 O(k) 空间复杂度吗?
1.使用上一题的思路,将每一层的数据存入容器中,最后返回需要的那一行的数据:
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<vector<int>> vec(rowIndex + 1); //创建存储所有数据的容器
if (rowIndex < 0) return vec[0]; //如果输入的行数小于0,返回空
if(rowIndex == 0) return {1}; //输入第0行,则返回1
for (int i = 0; i <= rowIndex; ++i) //此处与上一题一致
{
vec[i].push_back(1);
for (int j = 0; j < i; ++j)
{
if (i > j && j != 0)
vec[i].push_back(vec[i-1][j] + vec[i - 1][j-1]);
}
if (i > 0)
vec[i].push_back(1);
}
return vec[rowIndex]; //返回所需的那一行
}
};
2.利用杨辉三角的性质,需要两个for循环,除了第一个数为1之外,后面的数都是上一次循环的数值加上它前面位置的数值之和,不停地更新每一个位置的值,便可以得到第n行的数字:
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> vec(rowIndex + 1);
if (rowIndex < 0) return vec;
for (int i = 0; i <= rowIndex; ++i) {
if ( i == 0) { //当为第0行时,数值为1
vec[0] = 1;
continue;
}
for (int j = rowIndex; j >= 1; --j) { //每一行的数据(由上一行得出)
vec[j] = vec[j] + vec[j-1];
}
}
return vec;
}
};
②买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4] 输出: 5 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:
输入: [7,6,4,3,1] 输出: 0 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
1.用一个变量记录遍历过程中的最小值,然后每次计算当前值和这个最小值之间的差值,更新该最大差值,当遍历完成后得出最大利润:
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty() || prices.size() == 1)
return 0;
int res = 0, buy = INT_MAX;
for (int price : prices)
{
buy = min(buy, price); //遍历得出最小值
res = max(res, price - buy); //更新最大差值
}
return res;
}
};
买卖股票的最佳时机Ⅱ
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [7,1,5,3,6,4] 输出: 7 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
示例 2:
输入: [1,2,3,4,5] 输出: 4 解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。 因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:
输入: [7,6,4,3,1] 输出: 0 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
1.因为可以多次买入与卖出,所以只要第二天的股票价格比当天价格高,就可以在当天买入,第二天卖出,并将其加入差值,计算利润:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int res = 0, n= prices.size() - 1;
for (int i = 0;i < n; ++i)
{
if (prices[i] < prices[i + 1]) //如果第二天股票价格高于当天价格
res += prices[i+1] - prices[i]; //则计算其差值加入利润
}
return res;
}
};