给定一个数组,它的第 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。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
基本思路:暴力求解
int maxProfit(vector<int>& prices) {
int ans=0;
for(int i=0;i<prices.size();i++){
for(int j=i+1;j<prices.size();j++){
ans=max(ans,prices[j]-prices[i]);
}
}
return ans;
}
基本思路:单调栈
- 本问题的实质是,求左边较小的数和右边较大的数的差值,单调递增序列,可以考虑使用单调栈
int maxProfit(vector<int>& prices) {
int ans=0;
vector<int> stk;//使用vector,更方便操作。
prices.emplace_back(-1); //哨兵,保证遍历完栈
ans=0;
for(int i=0;i<prices.size();i++){
while(!stk.empty()&&stk.back()>prices[i]){
ans=max(ans,stk.back()-stk.front());
stk.pop_back();
}
stk.emplace_back(prices[i]);
}
return ans;
}
基本思路:动态规划
int maxProfit(vector<int>& prices) {
if(prices.size()<1)
return 0;
vector<int> dp1(prices.size(),0); //表示第i天持有股,可能第i天买入,也可能之前
vector<int> dp2(prices.size(),0); //表示第i天的最大收益,可能第i天卖出,也可能之前卖出
dp1[0]=-prices[0];
dp2[0]=0;
for(int i=1;i<prices.size();i++){
dp1[i]=max(dp1[i-1],-prices[i]); //因为是负的,表示尽量买入价格最低==>贪心,找到已经遍历的序列中的最小价格
dp2[i]=max(dp2[i-1],dp1[i-1]+prices[i]); //卖出价格尽量高
}
return dp2[prices.size()-1];
}
//空间优化,只与前面的状态有关
int maxProfit(vector<int>& prices) {
if(prices.size()<1)
return 0;
int dp1=-prices[0];
int dp2=0;
for(int i=1;i<prices.size();i++){
dp2=max(dp2,dp1+prices[i]);
dp1=max(dp1,-prices[i]);
}
return dp2;
}
基本思路:贪心算法,相当于求取每一个位置上的最大收益,记录已经遍历的序列的最小股价,当前值-最小股价,即为当前最大收益
int maxProfit(vector<int>& prices) {
int maxPro = 0, minPrice = INT_MAX;
for(int i = 0; i < prices.size(); i++) {
minPrice = min(minPrice, prices[i]);
maxPro = max(prices[i] - minPrice, maxPro);
}
return maxPro;
}