初级算法-买卖股票的最佳时机 II

买卖股票的最佳时机 II
解题思路:

  1. 贪心算法:
    没啥很复杂的,贪心算法的思路就是每次取得局部最优解,从而得到全局最优解,不过可能这个全局最优解并不是最优的。。
    针对上面那道题,我们每次都把增长的取到,累加就可以得到最大利润。
public int maxProfit(int[] prices) {
        int maxProfit = 0;
        for (int i = 1; i < prices.length; i++) {
            if (prices[i] > prices[i - 1]) {
                maxProfit += prices[i] - prices[i - 1];
            }
        }
        return maxProfit;
    }
  1. 动态规划算法:
    动态规划算法的思路是每次递推有两种选择,做还是不做,逐渐向下,好像一个展开的树,最终到达一个临界点获得最终的最大值后,逐层向上返回每层最大收益,最后得到全局最大收益;其和贪心算法的区别是贪心算法只关心局部的一个最优解,最终得到全局最优解,而这个全局最优解并不一定就真的是最优解,有点死心眼的感觉,而动态规划则纵观全局,得到最终全局最优解。
    本题和常规动态规划有一些差异是他有两个递推公式,而有两个递归公式的原因是前一天可能买入,可能没买入,这就导致如果前一天买入了那今天只能选择卖出或不卖出,而不能买入,而如果前一天没买入,那今天就只能选择买入或者不买入。
    下面来推导递推公式:首先我这里定义两个个参数:dp[i][0]作为当天不持有最大收益(利润)和dp[i][1]作为当天持有最大收益(利润),i是一共几天也就是题述prices的长度,我们明确,最后一天肯定是手里不持有股票收益最大,那么首先产生递推公式:
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);

这里对公式做一下解释:我最后这天也就是今天想不持有,那第一种可能是昨天我就没持有,那我今天不买就是了,那也就是公式里的dp[i-1][0],第二种可能是昨天我持有股票,那我今天就得把它卖掉,否则我就损失了这prices[i]的利润了,所以就是公式里dp[i-1][1]+ prices[i]。

然后我们可以发现,如果这么递推,我缺少了对倒数第二天也就是dp[i-1][1]这个最大利润的支持,那我们就为这个dp[i-1][1]也做一个递推公式:

dp[i-1][1] = Math.max(dp[i - 2][1], dp[i - 2][0] - prices[i]);

这里再对这个公式进行一下解释:倒数第二天也就是昨天我想持有,那第一种可能是我前天就持有的,那我昨天就继续持有就行了,也就是公式里的dp[i-2][1],而第二种可能是我前天并没持有,那我昨天就得买进来,也就是公式里的dp[i-2][0]- prices[i],这就达成了我昨天持有股票的目的。

再说过来,我昨天可以持有,那其实我今天依旧可以持有,只不过那不是最大利润罢了,今天不理他就行了,毕竟我们要写代码的嘛,何必要管到底是今天还是昨天呢,把最大收益返回就是了,这就可以把上面这个递推公式调整为:

dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);

这就是两个递推公式的由来。

而这个递推公式的临界就是第一天,那就设置两个值:

 dp[0][1] = -prices[0];//持有股票,刨掉成本
 dp[0][0] = 0;//不持有股票,没成本

最终得到我们的动态规划解法(摘自LeetCode):

public int maxProfit(int[] prices) {
    if (prices == null || prices.length < 2)
        return 0;
    int length = prices.length;
    int[][] dp = new int[length][2];
    //初始条件
    dp[0][1] = -prices[0];
    dp[0][0] = 0;
    for (int i = 1; i < length; i++) {
        //递推公式
        dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
        dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
    }
    //最后一天肯定是手里没有股票的时候,利润才会最大,
    //只需要返回dp[length - 1][0]即可
    return dp[length - 1][0];
}

以上均为本人自己理解,如有问题,欢迎大佬们留言~~

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值