leetcode 188 Best Time to Buy and Sell Stock IV

博客围绕设计算法求给定股票数组最多 k 次交易的最大利润展开。起初尝试用动态规划,时间和空间复杂度高,部分 case 超内存限制;又试过找波峰波谷放堆中取值,但遇 v1<v2&&p1<p2 情况无法解决。后借鉴他人做法解决问题,时间和空间复杂度降为 O(n),还附上代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most k transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

Example 1:

Input: [2,4,1], k = 2
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.

Example 2:

Input: [3,2,6,5,0,3], k = 2
Output: 7
Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4.
             Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.

这道题我一开始想用动态规划去做,转移方程是

dp[[j][m] = max(dp[k][m-1] + maxp[k+1][j]):dp[j][m]指的是前j天m次交易的最大收益,1<=j<n;2<=m<=k;1<=k<=j;时间复杂度是O(n^3),空间复杂度是O(n^2);很明显两者都太高了,有些case超出内存限制了;之前做Best Time to Buy and Sell StockⅢ的时候有尝试过找成对的波峰波谷,将差值放到大顶堆中,然后取前k个值。但是因为不知道如何处理v1<v2&&p1<p2的情况,有些case没法通过;但是我看了别人的做法,非常巧妙。当v1<v2&&p1<p2时,可以将(v1,p2),(v2,p1)代替(v1,p1),(v2,p2),这就完美解决了我上面的问题。唉,为什么我当初没有细想下去呢。。。。时间复杂度为O(n),空间复杂度也为O(n)。

下面附上第一第二次的代码

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) 
    {
        int n = prices.size();
        //cout<<n<<endl;
        if(n<2||k==0) return 0;
        vector<vector<int> > maxp_1 = maxp(prices);
        vector<vector<int> > dp(n,vector<int>(k+1,0));
        for(int i=1;i<n;i++)
        {
            dp[i][1] = maxp_1[0][i];
            cout<<i<<" "<<1<<" "<<dp[i][1]<<endl;
        }
        if(k==1) return dp[n-1][1];
        for(int j=1;j<n;j++)
        {
            for(int m=2;m<=k;m++)
                for(int i=1;i<=j;i++)
                {
                    dp[j][m] = max(dp[j][m],dp[i][m-1]+maxp_1[i+1][j]);
                    //cout<<i<<' '<<m<<" "<dp[i][m];
                }
        }
        return dp[n-1][k];
    }
    vector<vector<int> > maxp(vector<int>& price)
    {
        int n = price.size();
        vector<vector<int> > maxpv(n+1,vector<int>(n+1,0));
        for(int i=0;i<n;i++)
        {
            int minele = price[i];
            for(int j=i+1;j<n;j++)
            {
                maxpv[i][j] = max(maxpv[i][j-1],price[j]-minele);
                if(price[j]<minele) minele = price[j];
            }
        }
        return maxpv;
    }
};

 

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) 
    {
        stack<pair<int,int>> vp_pairs;
        priority_queue<int> profit;
        int n=prices.size();
        int v,p=0;
        int ans=0;
        while(p<n)
        {
            for(v=p;v<n-1&&prices[v]>=prices[v+1];v++);
            for(p=v+1;p<n&&prices[p]>=prices[p-1];p++);
            while(!vp_pairs.empty()&&prices[v]<=prices[vp_pairs.top().first])
            {
                profit.push(prices[vp_pairs.top().second-1]-prices[vp_pairs.top().first]);
                vp_pairs.pop();
            }
            while(!vp_pairs.empty()&&prices[p-1]>prices[vp_pairs.top().second-1])
            {
                profit.push(prices[vp_pairs.top().second-1]-prices[v]);
                v = vp_pairs.top().first;
                vp_pairs.pop();
            }
            vp_pairs.push({v,p});
        }
        while(!vp_pairs.empty())
        {
            profit.push(prices[vp_pairs.top().second-1]-prices[vp_pairs.top().first]);
            vp_pairs.pop();
        }
        for(int i=0;i<k&&!profit.empty();i++)
        {
            ans += profit.top();
            profit.pop();
        }
        return ans;
    }
};

ps:我老是会犯堆溢出的问题,在访问向量中元素的时候经常忘记做下标判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值