LeetCode--Best Time to Buy and Sell Stock IV(DP + 滚动数组)
来源:互联网 发布:强情节 知乎 编辑:程序博客网 时间:2024/06/05 16:02
题目:https://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/
题意:已知第1天、第2天......第N天的股票价格,每天只能进行一次买或者卖,且规定手里的股票卖出之前不能买进新的股票,问在最多进行K次交易的情况下,采用最优方案净利润能有多少。
分析:
1、设j天完成不超过i次交易能得到的最大收益是f(i,j),显然f(0,0) = 0,f(i, 1) = 0(因为只有1天不能完成任何交易)
2、对最后一天也就是第j天发生的情况进行分类,第j天可能没有买卖,也可能最后一次卖出手里的股票,即
f(i, j) = max{ f(i-1, j), f(i, j-1), f(i-1,k-1) + a[j] - a[k] },其中k >= 1 && k < j,即最后一天卖出的股票可能是第1天、第2天......第j-1天买入的股票
3、状态方程有了,似乎可以直接写了,但由于k的存在,这一算法的复杂度是O(k*n*n)的,在大数据情况下会TLE,我们看看能不能对后面这个f(i-1,k-1) + a[j] - a[k]做一些分析
4、我们令g(i, j) = f(i-1, k-1) - a[k],其中k >= 1 && k < j,那它表示什么意思呢,即最后第j天之前,最多进行了i-1次交易,且最后一次买入发生在第k天,这一过程之后手里money最多还有多少(或最少还欠多少),显然g(i, 1) = 0(因为第1天之前最多进行0次交易),g(i, 2) = f(i-1, 0) - a[1],将k带入,我们可以看到:
g(i, j) = max{ f(i-1, 0) - a[1], f(i-1, 1) - a[2], ..., f(i-1, j-2) - a[j-1] }
g(i, j+1) = max{ f(i-1, 0) - a[1], f(i-1, 1) - a[2], ..., f(i-1, j-2) - a[j-1], f(i-1, j-1) - a[j] }
= max{ g(i, j), f(i-1, j-1) - a[j] }
即g(i, j)的递推会用到f(i, j)的状态
5、将g(i, j)带入我们的状态方程,则
g(i, j) = max{ g(i, j-1), f(i-1, j-2) - a[j-1] }
f(i, j) = max{ f(i-1, j), f(i, j-1), g(i, j) + a[j] }
可以看到g的当前状态仅和本层前一个状态、f的上一层前一个状态有关,f当前状态仅和上一层的当前状态、本层的前一个状态、g的当前状态有关,因此我们可以采用滚动数组的形式,仅保留2层状态,即能完成状态转移的过程
6、最后还有一个优化(有点像多重背包可以分成完全背包和0-1背包):
当2k >= n时,即我们可以做到在任意一天买入任意之后一天卖出,在直方图中容易看出这相当于只要有利可图我们就能获得
class Solution {public: int allProfit(vector<int>& prices){ int tot = 0; for(int i = 1; i < prices.size(); ++i){ tot += max(0, prices[i] - prices[i-1]); } return tot; } int maxProfit(int k, vector<int> &prices) { int n = prices.size(); if(k * 2 >= n) return allProfit(prices); vector<int> mem((n + 1) * 2, 0); int *pref = &mem[0], *curf = &mem[n+1], g, *a = &prices[0] - 1; for(int i = 1; i <= k; ++i){ //递推第1天和第2天的情况,因为比较特殊 curf[1] = 0; //g[1] = 0, g[2] = pref[0] - a[1] curf[2] = max(0, a[2] - a[1]); g = -a[1]; //递推之后的情况 for(int j = 3; j <= n; ++j){ g = max(g, pref[j-2] - a[j-1]); curf[j] = max(max(pref[j], curf[j-1]), g + a[j]); } swap(pref, curf); } return pref[n]; }};
- LeetCode--Best Time to Buy and Sell Stock IV(DP + 滚动数组)
- 【LeetCode】Best Time to Buy and Sell Stock IV 动态规划dp解法(C++)
- [LeetCode] Best Time to Buy and Sell Stock IV
- leetcode: Best Time to Buy and Sell Stock IV
- LeetCode(188) Best Time to Buy and Sell Stock IV
- Best Time to Buy and Sell Stock IV -- leetcode
- Best Time to Buy and Sell Stock IV--LeetCode
- LeetCode : Best Time to Buy and Sell Stock III & IV
- Best Time to Buy and Sell Stock IV Leetcode Java
- LeetCode: Best Time to Buy and Sell Stock IV
- leetcode 188---Best Time to Buy and Sell Stock IV
- LeetCode Best Time to Buy and Sell Stock IV
- [leetcode] 188.Best Time to Buy and Sell Stock IV
- LeetCode - Best Time to Buy and Sell Stock IV
- [LeetCode][Java] Best Time to Buy and Sell Stock IV
- 【leetcode】Best Time to Buy and Sell Stock IV
- leetcode 188: Best Time to Buy and Sell Stock IV
- [leetcode] 188.Best Time to Buy and Sell Stock IV
- mdrill安装(1)
- 工厂分布距离最短
- c语言实现strcpy功能
- Anagrams
- Word转换成PDF文件在线转换
- LeetCode--Best Time to Buy and Sell Stock IV(DP + 滚动数组)
- Python 操作 json
- Intent跳转方式
- 在java代码中将图片转变为base64位代码 并且在浏览器下展示base64编码的图片
- smokeJS
- mdrill安装(2)
- 编程过程中常见的10大算法
- eclipse failed to create the java virtual machine
- mdrill安装(3)