一、题目概述
给定一个数组,其中第i个元素代表第i天股票的价格。
如果你最多被允许完成一次交易(即,购买并抛售一份股票),设计一种算法寻找最大利润。
- 示例1:
Input: [7, 1, 5, 3, 6, 4]
Output: 5
最大差值为6-1=5,(而非7-1=6,因为卖出价格需要高于买入价格) - 示例2:
Input: [7, 6, 4, 3, 1]
Output: 0 此种情况下,不进行交易,利润最大为0。
函数原型:
int maxProfit(vector<int>& prices)
二、编程思路
本题目最简单的思路是对于每一个买入价格prices[i],计算卖出价格为prices[j],
i≤j≤prices.size()
,求利润的最大值,然而此种算法的时间复杂度为
O(n2)
,若直接以此思路编程,会超过限制时间。
仔细观察可以发现本问题可以转化为最大连续子序列和的问题。
求
max{prices[j]−prices[i]},i≤j并且i,j∈[0,prices.size())
,
即求
max{prices[j]−prices[j−1]+prices[j−1]−prices[j−2]+prices[j−2]−prices[j−3]+…+prices[i+1]−prices[i]},i≤j并且i,j∈[0,prices.size())
令 diff[i]=prices[i]−prices[i−1] ,则上式可以转变为
max{diff[j]+diff[j−1]+...+diff[i+1]},i≤j并且i,j∈[0,prices.size())
即是最长连续子序列问题。
最长子序列
对于序列diff,令dp[i]表示diff[i]结尾的最长子序列之和,则有如下状态转移方程:
dp[0]=max{0,diff[0]}
dp[1]=max{0,diff[0],diff[1],diff[0]+diff[1]}=max{dp[0],dp[0]+diff[1]}
...
diff[i]=max{dp[i−1],dp[i−1]+diff[i]}
三、程序设计
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()<2) return 0;
vector<int> diff;
for(int i=1;i<prices.size();i++){
diff.push_back(prices[i]-prices[i-1]);
}
int max=0,global_max=0;
for(int i=0;i<diff.size();i++){
max+=diff[i];
if(max>global_max) global_max=max;
if(max<0) max=0;
}
return global_max;
}
};
四、实验心得
可以对问题进行适当转化,使其变为经典问题进行解决。