
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;
}
};
5.动态规划
条件 1:你不能在买入股票前卖出股票; 条件 2:最多只允许完成一笔交易。
dp[i][j]:下标为 i 这一天结束的时候,手上持股状态为 j 时,我们持有的现金数。 j = 0,表示当前不持股; j = 1,表示当前持股。
昨天不持股,今天什么都不做; 昨天持股,今天卖出股票(现金数增加),
昨天持股,今天什么都不做(现金数与昨天一样); 昨天不持股,今天买入股票(注意:只允许交易一次,因此手上的现金数就是当天的股价的相反数)。
知识点:
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;
}
};