关键词:“动态规划”、“买卖股票”
题目描述
这道题,有想到动态规划来做,但是没有想到合适的数组存储意义。看了几个对应题解,都是以对应时间点的利润作为含义。读了好几个,才明白其中含义。相比较之下,个人认为,以当前账户余额最为贴切。(利润是一个两个状态的资产的差值的描述,且当用户拥有某个股票时,这股权也是用户资产的一部分,而前者使用利润来描述时是忽略了这样的含义)
分析
根据题目内容,我们可以知道:
- 可以进行多次交易
- 手续费的存在对频繁的买卖行为形成约束。
解题思路(动态规划)
存储含义
用account[i] [0] 表示在第i天没有拥有股票的账户余额最大值;
用account[i] [1] 表示在第i天拥有股票情况下的账户余额最大值;
转移关系
第i+1天,没有股票的最大账户余额account[i+1] [0]有两种状态转移而来:
在前一天就是不拥有股票的最大账户余额 account[i] [0]
在前一天拥有股票的账户最大余额 account[i] [1],并在第i+1天抛售
第i+1天,有股票的最大账户余额account[i+1] [1]有两种状态转移而来:
在前一天就是不拥有股票的最大账户余额 account[i] [0],并在第i+1天购买
在前一天拥有股票的账户最大余额 account[i] [1]
初始状态
假设初始账户余额为0,则在不拥有股票的情况下,最终账户余额就是所获得的利润。
第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刷题笔记,我希望能够提供相关的解题分析和部分相关问题的链接,使得大家能获得一个较好的分析与相关问题的比较。
偶尔会进行类似题目的总结工作,有需要的读者可以对这份工作进行关注。
如果你发现有相关的错误或者表述不当不清晰的地方,请进行评论,我会尽快进行核对勘正。