https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/description/
【题意】
给定n天股市的票价,最多交易k次,问最大盈利是多少,手上不能同时持有两支股票。
【思路】
考虑加入当天买当天卖这种情况,问题转换为n天总共交易k次(不是最多),因为后一次的买一定在前一次卖之后,所以需要dp[i][j]表示前i天交易j次且最后一次交易在第i天的最大利润。则
dp[i][j]=max(a[i]-a[k]+global[k-1][j-1]) 1<=k<=i
k=i表示当天买当天卖,global[i][j]表示max{dp[k][j]} 1<=k<=i
注意这里是global[k-1][j-1]而不是global[k][j],因为若最后一次交易恰好在第k天,则a[i]-a[k]+global[k][j-1]一共进行j-1次交易,而不是j次。
dp[i][j]=max(a[i]-a[k]+global[k-1][j-1])(1<=k<=i)
=max(a[i]-a[i-1]+a[i-1]-a[k]+global[k-1][j-1],global[i-1][j-1])) (1<=k<=i-1)
=max(a[i]-a[i-1]+dp[i-1][j],global[i-1][j-1]) (1<=k<=i-1)
【复杂度】
时间复杂度O(kn),空间可以用滚动数组,为O(1)
【AC】
1 class Solution { 2 public: 3 int maxProfit(int k, vector<int>& prices) { 4 int len=prices.size(); 5 if(len==0 || len==1) return 0; 6 if(k==0) return 0; 7 if(k>=len/2){ 8 int ans=0; 9 for(int i=1;i<len;i++){ 10 ans+=max(0,prices[i]-prices[i-1]); 11 } 12 return ans; 13 } 14 vector<int> local,global; 15 local.resize(len); 16 global.resize(len); 17 for(int i=0;i<len;i++){ 18 local[i]=global[i]=0; 19 } 20 for(int j=1;j<=k;j++){ 21 for(int i=1;i<len;i++){ 22 local[i]=max(local[i-1]+prices[i]-prices[i-1],global[i-1]); 23 } 24 for(int i=1;i<len;i++){ 25 global[i]=max(global[i-1],local[i]); 26 } 27 } 28 int ans=global[len-1]; 29 return ans; 30 } 31 };
local即为dp,表示局部最优解,global表示全局最优解
注意要特判k>=n/2,leetcode没有给出数据范围,k很大时会tle或mle,k若大于n/2,相当于可以无限次买卖,贪心就可以。
原文地址:https://www.cnblogs.com/itcsl/p/8951739.html