LeetCode 188. Best Time to Buy and Sell Stock IV
来源:互联网 发布:儿童电动牙刷价格淘宝 编辑:程序博客网 时间:2024/06/05 02:28
是LeetCode 123的升级版,题意也差不多,只是限制了不能超过k次买卖。话说我做到第四题才发现Stock是股票的意思,stone才是石头...
这道题做的挺坎坷了,用了好几种方法,做了一个晚上,最后还是看了题解稍微被提示一下才过的。
一开始我就想到了动态规划的方法,我用d[p][i][j] 来表示区间[i, j] 间至多买卖p次的最大利润。递推公式也很简单,为
d[p][i][j] = max(d[p][i][j] , d[p-1][i][q] + d[1][q+1][j] ) 。而d[1][i][j] 是可以先算出来的,算出来的复杂度为O(n2)。
然而这种动态规划的时间复杂度为O(n4)不用交都知道会超时。不过我还是交了,反而是超出了内存空间。
接下来我发现了d[p][i][j] 的第二维是没有必要的。然后我重新用一个新的数组a[i][j] 来表示区间[i, j] 买卖最多一次的最大利润,上面已经有提到,复杂度为O(n2)。而新的递推公式为,
d[p][j] = max(d[p][j], d[p-1][i-1] + a[i][j] ) ,总的时间复杂度为O(n3)。
然而还是超时了,超时的测试样例为一个k值很大的测试样例。我发现当k大于n/2时,多余的k并没有任何用处。所以我在开始的时候加上了一条 k = min (k , n/2 )。 但这依然改变了不了我超时的结果。
受到四边形不等式的启发,我在想能不能减去第三维不必要的枚举呢?
其实a[i][j] 在j增大的时候,并不是一直在增大。于是我用last[i][j] 来表示j后的第一个j ’ ,使得a[i][j'] > a[i][j]。这样j +1 ~ j’ - 1之间的枚举就能够省去了。计算所有last[i][j] 的时间复杂度为O(n2)。
最后的时间复杂度虽然还是O(n3),但由于last数组的存在可以加速不少。
再次提交发现不超时了,倒是内存反而超了...
无奈之下去看了题解,发现当k足够大的时候,要用到LeetCode 122的方法来做,即不限制买卖次数的情况,真坑...
修改之后终于过了,不过执行的时间基本属于倒数的了...而我在删去last数组之后再提交发现是超时的,说明这步的操作还是有必要的。代码如下,虽然感觉写的很糟糕,勉强能过而已:
const int maxk = 5000 + 5 ;const int maxn = 5000 + 5;# define INF 100000000typedef vector<vector<int> > Matrix ;Matrix d ;Matrix a ;Matrix last ;class Solution {public:int maxProfit2(vector<int>& prices) { int n = prices.size() ; if (n <= 1) return 0; vector<int> a ; a.push_back(INF) ; for (int i=0; i<n; i++) a.push_back(prices[i]) ; a.push_back(-INF) ; int ans = 0 ; int buy = 0 ; for (int i=1; i<=n; i++) { if (a[i] <= a[i-1]) buy = a[i] ; else if (a[i] >= a[i+1]) { ans += a[i] - buy ; } } return ans ; } int maxProfit(int k, vector<int>& prices) { int n = prices.size() ; if (!n) return 0 ; if (!k) return 0 ; if (k > n/2) return maxProfit2(prices) ; d = Matrix(k+1) ; a = Matrix(n) ; last = Matrix(n) ; for (int i=0; i<=k; i++) { for (int j=0; j<n; j++) d[i].push_back(0) ; } for (int i=0; i<n; i++) { for (int j=0; j<n; j++) { a[i].push_back(0) ; last[i].push_back(-1) ; } } // memset(d, 0, sizeof(d)) ; // memset(a, 0, sizeof(a)) ; for (int i=0; i<n; i++) { int mx = prices[i] ; for (int j=i+1; j<n; j++) { a[i][j] = max(a[i][j-1], prices[j] - mx) ; if (prices[j] < mx) { mx = prices[j] ; } } } for (int j=n-1; j>=0; j--) { int lx = j ; int lv = a[j][j] ; for (int i=j; i>=0; i--) { if (a[i][j] > lv) { for (int t=lx; t>i; t--) { last[t][j] = i ; } lv = a[i][j] ; lx = i ; } } } for (int p=1; p<=k; p++) { for (int j=1; j<n; j++) { d[p][j] = d[p-1][j] ; d[p][j] = max(d[p][j], a[0][j]) ; int i = j ; while (i != -1) { d[p][j] = max(d[p][j], d[p-1][i-1] + a[i][j]) ; i = last[i][j] ; } /*for (int i=0; i<j; i++) { d[p][j] = max(d[p][j], d[p-1][i] + a[i+1][j]) ; }*/ } } return d[k][n-1] ; }};
- [leetcode] 188.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
- [LeetCode] 188. 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
- LeetCode 188. 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
- Leetcode 188. 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: 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
- OpenGL on Windows using Sublime Test3
- Echarts学习记录——设置图表与容器的间隔
- c#中图片与Base64string 的转换
- 计划
- Xcode 8 崩溃 Error Domain=DVTPlugInErrorDomain Code=2
- LeetCode 188. Best Time to Buy and Sell Stock IV
- gcc 里不能使用gets() 和 puts() 函数的解决办法
- 悠然乱弹:开源中国GIT中Java分类下TOP10项目的活动情况分析
- git移除远程仓库某个文件夹
- git上传代码步骤
- 查看python的安装位置及好安装第三方库的位置
- 使用python实现一个简单的学生信息管理系统
- Linux权限管理命令
- MySQL中的锁(表锁、行锁)