关键词:“动态规划”、“买卖股票”
题目描述
这道题,有想到动态规划来做,但是没有想到合适的数组存储意义。看了几个对应题解,都是以对应时间点的利润作为含义。读了好几个,才明白其中含义。相比较之下,个人认为,以当前账户余额最为贴切。(利润是一个两个状态的资产的差值的描述,且当用户拥有某个股票时,这股权也是用户资产的一部分,而前者使用利润来描述时是忽略了这样的含义)
分析
根据题目内容,我们可以知道:
- 可以进行多次交易
- 手续费的存在对频繁的买卖行为形成约束。
解题思路(动态规划)
存储含义
用account[i] [0] 表示在第i天没有拥有股票的账户余额最大值;
用account[i] [1] 表示在第i天拥有股票情况下的账户余额最大值;
转移关系
第i+1天,没有股票的最大账户余额account[i+1] [0]有两种状态转移而来:
在前一天就是不拥有股票的最大账户余额 account[i] [0]
在前一天拥有股票的账户最大余额 account[i] [1],并在第i+1天抛售
a c c o u n t [ i + 1 ] [ 0 ] = m a x ( a c c o u n t [ i ] [ 0 ] , a c c o u n t [ i ] [ 1 ] + p r i c e s [ i + 1 ] − f e e ) account[i+1][0] = max( account[i][0], account[i][1]+prices[i+1]-fee ) account[i+1][0]=max(account[i][0],account[i][1]+prices[i+1]−fee)
第i+1天,有股票的最大账户余额account[i+1] [1]有两种状态转移而来:
在前一天就是不拥有股票的最大账户余额 account[i] [0],并在第i+1天购买
在前一天拥有股票的账户最大余额 account[i] [1]
a c c o u n t [ i + 1 ] [ 1 ] = m a x ( a c c o u n t [ i ] [ 1 ] − p r i c e s [ i + 1 ] , a c c o u n t [ i ] [ 1 ] ) account[i+1][1] = max( account[i][1]-prices[i+1], account[i][1] ) account[i+1][1]=max(account[i][1]−prices[i+1],account[i][1])
初始状态
假设初始账户余额为0,则在不拥有股票的情况下,最终账户余额就是所获得的利润。
第0天结束时
a
c
c
o
u
n
t
[
0
]
[
0
]
=
0
account[0][0] = 0
account[0][0]=0
a c c o u n t [ 0 ] [ 1 ] = − 1 ∗ p r i c e s [ 0 ] account[0][1] = -1*prices[0] account[0][1]=−1∗prices[0]
算法
INPUT: prices[], fee
OUTPUT: maxProfit
account[0][0] = 0
account[0][1] = 0-prices[0]
for i = 0 to prices.size()-1 :
account[i+1][0] = max( account[i][0], account[i][1]+prices[i+1]-fee )
account[i+1][1] = max( account[i][0]-prices[i+1], account[i][1] )
return account[prices.size()-1][0]
数据结构
数组
复杂度分析
时间复杂度和空间复杂度都是O(n)
代码实现
/*
dp
INPUT: prices, fee
OUTPUT: maxProfit
suppose:
dp[i][0] 不持有股票情况下的账户余额
dp[i][0] 持有股票情况下的账户余额
transition:
dp[i+1][0] = max( dp[i][0], dp[i][1]+prices[i+1]-fee )
dp[i+1][1] = max( dp[i][0]-prices[i+1], dp[i][1] )
initialization:
dp[0][0] = init_money
dp[0][1] = init_money-prices[0]
*/
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int size = prices.size() ;
int dp[size][2] ;
dp[0][0] = 0 ;
dp[0][1] = -1*prices[0] ;
for ( int i = 0 ; i < size-1 ; ++ i ){
dp[i+1][0] = max( dp[i][0], dp[i][1]+prices[i+1]-fee ) ;
dp[i+1][1] = max( dp[i][0]-prices[i+1], dp[i][1] ) ;
}
return max(dp[size-1][0], dp[size-1][1] );
}
};
相关问题
动态规划
买卖股票系列
-
LeetCode-122-买卖股票的最佳时机2 无限制买卖次数
-
LeetCode-123-买卖股票的最佳时机3 限制最多买卖2次
-
LeetCode-188-买卖股票的最佳时机4 限制最多买卖k次
-
LeetCode-309-买卖股票的最佳时机含冷冻期 限制冷冻期不可买卖
PS.
-
相比较于其他已有的leetcode刷题笔记,我希望能够提供相关的解题分析和部分相关问题的链接,使得大家能获得一个较好的分析与相关问题的比较。
-
偶尔会进行类似题目的总结工作,有需要的读者可以对这份工作进行关注。
-
如果你发现有相关的错误或者表述不当不清晰的地方,请进行评论,我会尽快进行核对勘正。