[leetcode122].为何此时贪心解是最优解 ?

【不知道是不是我想太多了,还是脑抽了?】
今天做了一个有意思问题,即122. Best Time to Buy and Sell Stock II 。简单地用中文描述问题,也就是用[ a1,a2,...,an ]表示一支股票在 n 个时刻的价格,问如何买卖股票可以使得收益最大。比如[1,2,6,8,9],可以在1的时候买入6的时候卖出,8的时候买入,9的时候卖出,此时收益为5+1=6。

本问题虽然很快就猜到一个贪心解,且看起来非常显然的解,并且完美地AC了。

class Solution(object):
    def maxProfit(self, prices):
        ans=0
        if len(prices)<=1:
            return 0
        for x in range(1,len(prices)):
            if prices[x]-prices[x-1]>=0:
                ans+=prices[x]-prices[x-1]
        return ans

绝大多数的博客、问题的discuss以及官网给出的解答都是仅仅一个贪心的策略(没有探讨为何是最优),即将所有最大的上升子区间加起来,如图所示,即将所有的上升区间
这里写图片描述
加起来,说实话这看起来很有道理。毕竟满足我们的常识:在最低价的时候买入,在最高价的时候卖出(如果我们能预知未来,恰好此题可以预知未来),看图也是很明显的。

但是我想,这不过是给出了一个贪心解,如何证明它是最优的呢?这个问题难道真的那么简单吗?为了逻辑的完整性,我们必须证明这样的构造(方法)恰好就是最优解,我下午思考了若干种情况,分别分类讨论了一下,搞了很久(是不是我想太多了?)

实际上现在我们的问题无非就是将数组划分为若干个“持股区间”,在左端点上买入,右端点上卖出,找出使得收益最大的“持股区间”。受到狗蔡的启发,实际上我发现只要讲问题足够好地数学化就可以了,我们设给定的数组为[a1,a2,...,an],设最优的“持股区间”为 X (实际上这样的区间是存在的,因为区间的总数有限,可以用隔板法可以得出区间总数),将其划分为n1个小区间,即[ a1,a2 ],…,[ an1,an ],设示性函数:

χ[ai+1,ai]={1,[ai+1,ai]X0,[ai+1,ai]⊄X

那么我们的目标函数就是:

maxi=1n1(ai+1ai)χ[ai+1,ai]

很显然,这已经是一个0,1规划问题。另外我们来看实际上如果一个连续的区间[ a1,a2 ],[ a2,a3 ]都是 X 的子集的话,可以看成是[a1,a3]符合我们的想法。由于示性函数是非负的,我们可以放缩它为:
i=1n1(ai+1ai)χ[ai+1,ai]=+Δaχ+Δaχ+Δaχ+Δa

等号成立条件为 (ai+1ai)0 的区间都使示性函数为1,否则为0,这恰好就是贪心算法的解。最优性得证。

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值