leetcode 股票买卖问题

方法1:动态规划法

https://mp.weixin.qq.com/s/voti73ay-Ko3mt0qwIDouQ

核心思路是找出第一次卖在哪天是最佳的

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        return f(k, prices);
    }
    
    int f(int k, vector<int>& prices) {
        if (prices.size() <= 1) return 0;        
        
        vector<vector<int>> memo(prices.size(), vector<int>(k+1, -1));
        
        return dp(prices, memo, 0, k);
    }
    
    int dp(vector<int>& prices, vector<vector<int>> memo, int start, int k)
    {
        if (start >= prices.size()) return 0;
        if (k == 0) return 0;
        if (memo[start][k] != -1) return memo[start][k];
        int res = 0;
        int cur_min = prices[start];
        //这里求得是第一次sell在哪天是最佳的
        for (int sell = start+1; sell < prices.size(); ++sell)
        {
            cur_min = min(cur_min, prices[sell]);
            res = max(res, prices[sell]-cur_min+dp(prices, memo, sell+1, k-1));
        }
        memo[start][k] = res;
        return res;        
    }      
};

 

方法2:状态机

https://mp.weixin.qq.com/s/_xxnQP7hDIBSTpPsok8QIg

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        return maxProfit_k_any(k, prices);
    }
    
    int maxProfit_k_inf(vector<int>& prices) {
        int dp_i_0 = 0;
        int dp_i_1 = INT_MIN;
        for (int i = 0; i < prices.size(); ++i)
        {
            int temp = dp_i_0;
            dp_i_0 = max(dp_i_0, dp_i_1+prices[i]);
            dp_i_1 = max(dp_i_1, temp-prices[i]);
        }
        return dp_i_0;
    }  
    
    int maxProfit_k_any(int k, vector<int>& prices)
    {        
        int n = prices.size();
        if (n<=1) return 0;
        if (k == 0) return 0;
        if (k > n/2)
            return maxProfit_k_inf(prices);
        
        int max_k = k;
        int dp[n][max_k+1][2] = {};       
        for (int i = 0; i < n; ++i)
        {
            dp[i][0][0] = 0;
            dp[i][0][1] = INT_MIN;
        }
        for (int i = 0; i < n; ++i)
        {
            for (int k = 1; k <= max_k; ++k)
            {
                if (i==0) // base case
                {
                    dp[0][k][0] = 0;
                    dp[0][k][1] = -prices[i];
                }
                else
                {
                    dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1]+prices[i]);
                    dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0]-prices[i]);
                }
            }
        }
        return dp[n-1][max_k][0];        
    }    
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值