给定一个数组,它的第 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:令状态 dp[i] 表示以 A[i] 作为末尾的连续序列的最大和(这里是说 A[i] 必须作为连续序列的末尾)。
步骤 2:做如下考虑:因为 dp[i] 要求是必须以 A[i] 结尾的连续序列,那么只有两种情况:
- 这个最大和的连续序列只有一个元素,即以 A[i] 开始,以 A[i] 结尾。(此时dp[i]只有一个元素,即A[i])
- 这个最大和的连续序列有多个元素,一直到 A[i] 结尾。(最大和是dp[i-1]+A[i])
所以,状态转移方程为:
dp[i] = max{A[i], dp[i-1]+A[i]}
边界:dp[0]=A[0],遍历完数组A后就可以得到dp,然后再取dp中的最大值即可,注意:若dp中的最大值小于0,则最大收益为0。
int maxProfit(vector<int>& prices) {
if (prices.empty())
return 0;
if(prices.size()==1)
return 0;
//转换为最长子序列和问题,首先将提给数组进行转换,以v[i]表示第i天与第i减一天股票价格的差价
vector<int> v(prices.size() - 1, 0);
for (int i = 0;i < prices.size() - 1;++i)
v[i] = prices[i + 1] - prices[i];
vector<int> dp(v.size(),0);
//边界条件
dp[0] = v[0];
for (int i = 1;i < v.size();++i)
dp[i] = max(v[i], v[i] + dp[i - 1]);
int k = dp[0];//在dp中找出最大值
for (int i = 1;i < dp.size();++i)
if (dp[i] > k)
k = dp[i];
if(k>0)
return k;
else
return 0;
}
解法二:
思路:与解法一类似,只有正的值才会对最大子序列和有贡献,每次将sum更新为sum和curr中的较大者.
class Solution {//不能用暴力求解法,会超时,转换为最长子序列和
public:
int maxProfit(vector<int>& prices) {
if(prices.empty()||prices.size()==1)
return 0;
//转换为最长子序列和的问题
vector<int> temp;
for(int i=1;i<prices.size();++i)
temp.push_back(prices[i]-prices[i-1]);
//然后对temp求最长子序列和
int curr=temp[0];
int sum=temp[0];
for(int i=1;i<temp.size();++i)
{
if(curr>=0)//只有curr为正值时,才计入最大子序列和
curr+=temp[i];
else
curr=temp[i];//否则,更新curr
if(curr>sum)
sum=curr;
}
if(sum>0)
return sum;
else
return 0;
}
};