解体思路
-
乍一看容易被吓到,实际上很简单。
-
只要记录 [ 0 , . . . , i − 1 ] [0,...,i-1] [0,...,i−1]的最小值 m i n _ min\_ min_就可以了,然后我们要的结果其实就是 m a x ( p r i c e s [ i ] − m i n _ , r e s ) , i = 0 , . . . , n − 1 max(prices[i]-min\_,res),i=0,...,n-1 max(prices[i]−min_,res),i=0,...,n−1
-
更新一下题目,如果允许多次买卖,那么我们规定两种状态
- d p [ i ] [ 0 ] dp[i][0] dp[i][0]表示当前手中有股票,第 i i i天结束后我们得到的最大的收入。
- d p [ i ] [ 1 ] dp[i][1] dp[i][1]表示当前手中没有股票,第 i i i天结束后我们得到的最大的收入。
-
状态转移方程如下:
-
d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 1 ] − p r i c e s [ i ] , d p [ i − 1 ] [ 0 ] ) ; dp[i][0]=max(dp[i-1][1]-prices[i],dp[i-1][0]); dp[i][0]=max(dp[i−1][1]−prices[i],dp[i−1][0]);
d p [ i ] [ 1 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] + p r i c e s [ i ] ) ; dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i]); dp[i][1]=max(dp[i−1][1],dp[i−1][0]+prices[i]);
-
实现代码
// 允许多次买卖得到的最大的钱的数目
// class Solution {
// public:
// int dp[10005][2];
// int maxProfit(vector<int>& prices) {
// int n=prices.size();
// if(n<=0){
// return 0;
// }
// dp[0][0]=-prices[0];
// dp[0][1]=0;
// for(int i=1;i<n;i++){
// dp[i][0]=max(dp[i-1][1]-prices[i],dp[i-1][0]);
// dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i]);
// }
// int res=dp[n-1][1];
// printf("%d\n",res);
// return res;
// }
// };
// 一个O(n^2)的dp的做法
// class Solution {
// public:
// int dp[100005];
// int maxProfit(vector<int>& prices) {
// int n=prices.size();
// if(n<=1){
// return 0;
// }
// dp[0]=0;
// dp[1]=max(0,prices[1]-prices[0]);
// for(int i=2;i<n;i++){
// for(int j=0;j<i;j++){
// dp[i]=max(dp[i],prices[i]-prices[j]);
// }
// dp[i]=max(dp[i-1],dp[i]);
// }
// int res=dp[n-1];
// printf("%d\n",res);
// return res;
// }
// };
class Solution {
public:
int dp[100005];
int maxProfit(vector<int>& prices) {
int n=prices.size();
if(n<=0){
return 0;
}
int min_=prices[0];
int res=0;
for(int i=1;i<n;i++){
min_=min(min_,prices[i]);
res=max(prices[i]-min_,res);
}
printf("%d\n",res);
return res;
}
};