赞
踩
1.暴力法:
class Solution { public: int maxProfit(vector<int>& prices) { int n = prices.size(); int maxProfit = 0; for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { maxProfit = max(maxProfit, prices[j] - prices[i + 1]); } } return maxProfit; } };
2.一次遍历
class Solution { public: int maxProfit(vector<int>& prices) { int maxProfit = 0;//初始最高收益为0 int lowPrice = prices[0];//假设prices[0]为最低股价 for (vector<int>::size_type i = 1; i < prices.size(); i++) { //如果当日股价比最低股价还低,那么更新最低股价 if (prices[i] < lowPrice) { lowPrice = prices[i]; } else//如果当日股价比最低股价高,那么判断如果当日卖出股票获得的收益是否比记录在案的最高收益大 { maxProfit = max(maxProfit, prices[i] - low】k rice);//prices[i] - lowPrice:当日,、/*】/股价卖出的股价减去买入的最低股价 } } return maxProfit; } };
3.双指针解决
class Solution {
public:
int maxProfit(vector<int>& prices)
{
int maxPro = 0;
int Min = prices[0];
for (vector<int>::size_type i = 1; i < prices.size(); i++)
{
Min = min(Min, prices[i]);
maxPro = max(maxPro, prices[i] - Min);
}
return maxPro;
}
};
4.单调栈解决
class Solution { public: int maxProfit(vector<int>& prices) { stack<int> s; int maxPro = 0;//初始最大利润为0 s.push(prices[0]);//第一天的股价最低 for (int i = 0; i < prices.size(); i++) { if (prices[i] < s.top())//满足条件,更新最低股价 { s.pop(); s.push(prices[i]); } else { maxPro = max(maxPro, prices[i] - s.top()); } } return maxPro; } };
条件 1:你不能在买入股票前卖出股票;
条件 2:最多只允许完成一笔交易。
dp[i][j]:下标为 i 这一天结束的时候,手上持股状态为 j 时,我们持有的现金数。
j = 0,表示当前不持股;
j = 1,表示当前持股。
注意: 这个状态具有前缀性质,下标为 i 的这一天的计算结果包含了区间 [0, i] 所有的信息,因此最后输出 dp[len -1][0]。
说明:
使用「现金数」这个说法主要是为了体现 买入股票手上的现金数减少,卖出股票手上的现金数增加 这个事实;
「现金数」等价于题目中说的「利润」,即先买入这只股票,后买入这只股票的差价;
因此在刚开始的时候,我们的手上肯定是有一定现金数能够买入这只股票,即刚开始的时候现金数肯定不为 0,但是写代码的时候可以设置为0。极端情况下(股价数组为 [5, 4, 3, 2, 1]),此时不发生交易是最好的
推导状态转移方程:
dp[i][0]:规定了今天不持股,有以下两种情况:
昨天不持股,今天什么都不做;
昨天持股,今天卖出股票(现金数增加),
昨天持股,今天什么都不做(现金数与昨天一样);
昨天不持股,今天买入股票(注意:只允许交易一次,因此手上的现金数就是当天的股价的相反数)。
知识点:
class Solution { public: int maxProfit(vector<int>& prices) { int days = prices.size(); //特殊情况,如果天数只有一天,那么最大利润为0,因为一旦买入必须卖出,并且只发生一次 if (days == 1) { return 0; } //创建一个dp二维数组 int (*dp)[2] = new int[days][2]; //初始值:第一天的状态 dp[0][0] = 0;//第一天不买入股票,那么当前现金数为0 dp[0][1] = -prices[0];//第一天买入股票,那么当前现金数为0减去第一天的股价 //从第二天开始遍历 for (int i=1;i<days;i++) { //如果第i天没有持股,说明第i-1天有两种状态:没有持股第二天也不买,或者持有股票第二天卖出 dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]+prices[i]); //如果第i天持股了,说明第i-1天有两种状态:持股第二天不卖,不持股买入第二天的股票 dp[i][1] = max(dp[i - 1][1],-prices[i]); } return dp[days- 1][0];//我们要计算最后的最大利润,即最后我们手上有多少钱,因为初始钱为0 } };
复杂度分析:
6.动态规划的空间优化-----滚动数组
class Solution { public: int maxProfit(vector<int>& prices) { int days = prices.size(); //特殊情况,如果天数只有一天,那么最大利润为0,因为一旦买入必须卖出,并且只发生一次 if (days == 1) { return 0; } //创建一个dp二维数组 int (*dp)[2]= new int[2][2]; //初始值:第一天的状态 dp[0][0] = 0;//第一天不买入股票,那么当前现金数为0 dp[0][1] = -prices[0];//第一天买入股票,那么当前现金数为0减去第一天的股价 //从第二天开始遍历 for (int i=1;i<days;i++) { //如果第i天没有持股,说明第i-1天有两种状态:没有持股第二天也不买,或者持有股票第二天卖出 dp[i%2][0] = max(dp[(i-1)%2][0], dp[(i - 1)%2][1]+prices[i]); //如果第i天持股了,说明第i-1天有两种状态:持股第二天不卖,不持股买入第二天的股票 dp[i%2][1] = max(dp[(i - 1)%2][1],-prices[i]); } return dp[(days- 1)%2][0];//我们要计算最后的最大利润,即最后我们手上有多少钱,因为初始钱为0 } };
复杂度分析:
7.对状态转移方程的空间优化
下标为 i 的行并且状态为 0 的行参考了上一行状态为 0 和 1 的行;
下标为 i 的行并且状态为 1 的行只参考了上一行状态为 1的行。
class Solution { public: int maxProfit(vector<int>& prices) { int days = prices.size(); //特殊情况,如果天数只有一天,那么最大利润为0,因为一旦买入必须卖出,并且只发生一次 if (days == 1) { return 0; } int* dp = new int[2]; dp[0] = 0; dp[1] = -prices[0]; for (int i = 0; i < days; i++) { dp[0] = max(dp[0], dp[1] + prices[i]); dp[1] = max(dp[1],-prices[i]); } return dp[0]; } };
8.贪心算法
class Solution { public: int maxProfit(vector<int>& prices) { int len = prices.size(); int lowerPrice = prices[0]; int maxPro = 0; for (int i=0; i < len; i++) { if (prices[i] < lowerPrice) lowerPrice = prices[i]; else maxPro = max(maxPro, prices[i] - lowerPrice); } return maxPro; } };
9.参照最大子序列和的解法
class Solution { public: int maxProfit(vector<int>& prices) { int len = prices.size(); int cur = 0; int Max = cur; //注意i的初始值为1,因此要计算前一个元素减去后一个元素的值 for (int i = 1; i < len; i++) { //这里max(cur,0)是因为如果当前的cur都小于0了,那么只会越累加得到的值越小,所以直接从后一个值开始累加,相当于累加初始值重置为0 cur = max(cur, 0) + prices[i] - prices[i - 1]; Max = max(Max, cur);//判断当前的最大子序列和是否需要更新 } return Max; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。