Example One:
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
Example Two:
给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
我在思考第一道题目的时候,首先想到的是维护一个递增栈,因为只要获取利润,买入时价格必然低于卖出的价格,那么只需要在递增栈中取首尾数据即可得到最大利润。但这种想法很快被我抛弃了,因为当递增栈中突然出现一个极大的值,则会被我们丢弃,从而无法获取最佳解。其次我想到,找到最值,然后相减即可;但如果出现最小值在最大值的右侧怎么办?
那么假如第 i 天买入,第 j 天(j > i)卖出,如果第 j + 1 天的价格高于第 j 天,那么在第 j + 1 天卖出肯定赚更多的钱;假如第 j + 1 天的价格低于第 j 天但高于第 i 天,那么就不需要考虑;但假如第 j + 1 天的价格低于第 i 天,那么第 j + 1 天以后的数据就和第 i 天无关,所以后面的结果只和第 j + 1 天有关。
而第二题如果也按照第一题的贪心思路去解,则会发现后面数值尽管比前面的小,但因为底边变长了,所以数值上无法确定大小。这似乎用贪心算法无法解决,但我们可以换一种思路。使用两个指针,分别指向头 i 尾 j ,然后依次逼近中心。假如 i < j ,那么如果i + 1 < i,那么i + 1就不需要考虑了,因为高变小了底也变小了,所以头指针可以往中心走近一格,如此贪心法完美解决该问题!