动态规划之股票买卖

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

示例:

输入: [1,2,3,0,2]
输出: 3 
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

这是leecode上的一道题,主要利用动态规化解,关键是找到状态转移方程:

设:[1,2,3,0,2],选定一天为是否卖出股票

状态转移方程为:F[i]=max(buy_and_sell(k,i)+F[k-2] | k=i-1..0, F[i-1])。F[i]代表第i天卖出的最大收益,buy_and_sell(k,i)代表从k天买入并在i天卖出的收益,同时若是k天买入,那入之前的最大收益肯定是F[k-2]。

 

代码如下:

int max(int a,int b){
    if(a < b){
        return b;
    }

    return a;
}

int buysell(int* prices, int buyday,int sellday){
    if(prices[sellday] > prices[buyday]){
        return prices[sellday] - prices[buyday];
    }

    return 0;
}

int maxProfit(int* prices, int pricesSize){
    int i;
    int maxvalue;
    int today,buyDay;
    if(pricesSize <=1){
        return 0;
    }

    int *MaxProfitData = malloc(pricesSize * sizeof(prices[0]));
    if(MaxProfitData == NULL){
        return 0;
    }
    
    MaxProfitData[0] = 0;
    
    for(today=1;today<pricesSize;today++){
        maxvalue = 0;
        for(buyDay=today-1;buyDay>=0;buyDay--){
            int value = buysell(prices,buyDay,today);

            if(buyDay >=2)
                value += MaxProfitData[buyDay-2];

            if(maxvalue < value){
                maxvalue = value;
            }
        }

        MaxProfitData[today] = max(maxvalue,MaxProfitData[today-1]);
    }

    maxvalue = MaxProfitData[pricesSize-1];
    free(MaxProfitData);

    return maxvalue;
}

F[i]=max(buy_and_sell(k,i),F[k-2]|k=0...i-1 , F[i-1])事实上并不需要k从0...i-1完全遍历,因为出现最大收益只可能出现上一次F[i-1]时的最早买入时间至i之间,并不需要考虑之前的。通过记录上一次的买入时间,优化之后代码如下:

int max(int a,int b){
    if(a < b){
        return b;
    }

    return a;
}

int buysell(int* prices, int buyday,int sellday){
    if(prices[sellday] > prices[buyday]){
        return prices[sellday] - prices[buyday];
    }

    return 0;
}

int maxProfit(int* prices, int pricesSize){
    int i;
    int maxvalue;
    int today,buyDay;
    if(pricesSize <=1){
        return 0;
    }

    int *MaxProfitData = malloc(pricesSize * sizeof(prices[0]));
    if(MaxProfitData == NULL){
        return 0;
    }
    int *MaxProfitBuyDay = malloc(pricesSize * sizeof(prices[0]));
    if(MaxProfitBuyDay == NULL){
        return 0;
    }
    
    MaxProfitData[0] = 0;
    MaxProfitBuyDay[0] = 0;
    for(today=1;today<pricesSize;today++){
        maxvalue = 0;
        int maxvalue_buyday = 0;
        for(buyDay=today-1;buyDay>=MaxProfitBuyDay[today-1];buyDay--){
            int value = buysell(prices,buyDay,today);

            if(buyDay >=2)
                value += MaxProfitData[buyDay-2];

            if(maxvalue < value){
                maxvalue = value;
                maxvalue_buyday = buyDay;
            }
        }
        
        MaxProfitData[today] = max(maxvalue,MaxProfitData[today-1]);

        if(maxvalue > MaxProfitData[today-1]){
            MaxProfitBuyDay[today] = maxvalue_buyday;
        }else{
            MaxProfitBuyDay[today] = MaxProfitBuyDay[today-1];
        }
    }

    maxvalue = MaxProfitData[pricesSize-1];
    free(MaxProfitData);
    free(MaxProfitBuyDay);
    
    return maxvalue;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值