leetcode-121

作业题目

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

暴力破解

如果我每天每天都买,每天都卖,最后进行对比,我终究能够找到获利最大那天(虽然肯定是亏本)。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        last_day = len(prices)
        earn = []
        for buy_day in range(0, last_day - 1):
            buy_price = prices[buy_day]
            for sell_day in range(buy_day+1, last_day):
                sell_price = prices[sell_day]
                sell_earn = sell_price - buy_price
                earn.append(sell_earn)
        return max(earn)

直接判断

我关心的只是最高价值,所以max

但是这一步我是不是可以在循环中完成,融入流程,就可以省略容器了。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        last_day = len(prices)
        max_earn = 0
        for buy_day in range(0, last_day - 1):
            buy_price = prices[buy_day]
            for sell_day in range(buy_day+1, last_day):
                sell_price = prices[sell_day]
                sell_earn = sell_price - buy_price
                if sell_earn > max_earn:
                    max_earn = sell_earn
        return max_earn

买入时机

假如我今天卖,我赚多少具体和什么相关呢?

没毛病,必定和我买入的那天的价格相关,earn = sell_price - buy_price

也就是说,今天卖出的话,我必定是以今天之前的最低价格进行买入的。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        last_day = len(prices)
        max_earn = 0
        min_buy_price = int(1e9)
        for buy_day in range(0, last_day - 1):
            buy_price = prices[buy_day]
            if buy_price < min_buy_price:
                min_buy_price = buy_price
            for sell_day in range(buy_day+1, last_day):
                sell_price = prices[sell_day]
                max_sell_earn = sell_price - min_buy_price
                if max_sell_earn > max_earn:
                    max_earn = max_sell_earn
        return max_earn

当前状态

前面已经做了这么一个操作:将最后的比对融入到每次循环中,丢弃容器

现在也有一个问题,那就是我们今天要做什么。

整道题的思路,然我们以为这是必要的:在之前的某一天买入,在后面的某一天卖出

但是,这一天到底是哪天,这是不确定的。

就是这个原因,导致我们必须标记买入的那一天,然后再标记卖出的那一天。

现在,就决定今天的事情吧,我要卖出还是买入


如果我今天要买入,那么,今天的价格必定比以前的价格要低today_price < before_min_price

如果我今天要卖出,那么,今天的收益必定比以前的收益要搞today_earn > before_max_earn


更有意思的是,我们并非要买入才面临卖出,如果我们买了一个垃圾股,每天都面临卖出。

我们在第一天并非就只能买入,就这样,每天都是今天,每天我们都要思考。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        before_max_earn = 0
        before_min_price = int(1e9)
        for today_price in prices:
            today_earn = today_price - before_min_price
            if today_earn > before_max_earn:
                before_max_earn = today_earn
            if today_price < before_min_price:
                before_min_price = today_price
        return before_max_earn

总是说某一天,这表示时间是受我们管控的。

我们选择的是管理时间,但是我觉得还有一个选择,那就是回到过去

伴随容器是一个浪费的操作,但是我觉得它告诉了我们一个隐含的真理:我们是可以在多个时间中进行选择的

回顾一下当时的操作:

  • 每天都进行买入
  • 每天都进行卖出
  • 计算每天的收益
  • 选择最高的获利

但是,是什么让我们变得愚蠢。没错,就是因为聪明,自作聪明。

当我们有了更方便的方式,我们就更想直接的获取答案。

不过别忘记一点,我们有更聪明的方式,只能改变我们自己,却改变不了事实本身。

因此,我们的直接,只能针对那些本来就能够直接的事情。

就当前的事情来说,它不能够完全的直接,我们妄想整体的直接,就颠覆了事实本身,脱离最初的目的了。


对于这道题目,错误的思想(对我个人而言),就是明白了哪天该卖出或者买入(if)。

然后,妄想直接的选定那一天。

最原始,最粗糙,最笨拙的方式中,它每天都是进行买入卖出的。

这在能够判断是否买入卖出的时候的确是显得愚蠢,但是真理(关于这道题)是

就算你什么也不做,也需要过完这一天,过完每一天。

只有全部经历完成,你才能评定,才能选定获利最高的那一天。

关于递归

递归是计算自身,但是它之所以方便,不是它本身,而是一种思想:拆解,分而治之

将庞大的东西按照最小的组织关联起来

最近喜欢上了闭包这个东西,没错,可以将递归看做是一种闭包。

每次的递归的深入,都是一个拆包的过程,每一次递归的回溯,就是包的组织过程。

  • 先将复杂的东西拆解为简单的东西,进行计算
  • 然后将简单的计算结果,再层级的组合成为复杂的东西

让人惊叹的是,它的简单计算和开闭过程是如此的简单,就是这么简单的规则,可以构成无限的复杂。

尤为重要的是,它拆解之后,每个分支的无关性,每个小包,都是如此的独立,无怪乎能够进行简单计算。

自圆满,无依赖,或者可以拆解为更细的闭包,范围不溢出,又是它本质的一种。

代码修饰

或者,这个代码还能更短小一些

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        before_max_earn = 0
        before_min_price = int(1e9)
        for today_price in prices:
            before_max_earn = max(before_max_earn, today_price - before_min_price)
            before_min_price = min(before_min_price, today_price)
        return before_max_earn

再进一步

按照这个思路,还能够再进一小步

  • 有必要每天计算收益,然后对比么

可见的是,如果买入价格是一定的,我们要想收益更高,应该卖的更贵。

只有超过了原来更高的卖出价格,才有必要进行卖出。


class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        before_max_earn = 0
        before_min_price = int(1e6)
        before_max_sell_price = 0
        for today_price in prices:
            if today_price > before_max_sell_price or today_price < before_min_price:
                before_max_sell_price = today_price
                today_earn = today_price - before_min_price
                if today_earn > before_max_earn:
                    before_max_earn = today_earn
                if today_price < before_min_price:
                    before_min_price = today_price
        return before_max_earn

当然,如果存在买入,对比的卖出价格是以买入价格为准的,需要进行更新。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值