题目描述
Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Input: [7, 1, 5, 3, 6, 4] Output: 5 max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)
Example 2:
Input: [7, 6, 4, 3, 1] Output: 0 In this case, no transaction is done, i.e. max profit = 0.
这道题归在动态规划里头,我的算法方面很薄弱,所以想了好一会儿没想出来递推方程。
就先暴力解决。
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
max_profit = 0
for j in range(len(prices)):
current_price = prices[j]
for i in range(j+1,len(prices)):
if prices[i] > current_price :
temp_max_profit = prices[i] - current_price
if temp_max_profit > max_profit:
max_profit = temp_max_profit
return max_profit
这个结果是没错… 但是Time Limit error了。因为给出了一个很庞大的数据。这个时间复杂度O(n^2),还是太大了。
用动态规划的思想:
a[i]数组表示,到第i个元素为止,能获得的最大利润。
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
max_profit = 0
a = [0] * len(prices)
for i in range(1,len(prices)):
min_price = min(prices[:i])
a[i] = prices[i] - min_price
max_profit = max(a[i],max_profit)
return max_profit
这个时间复杂度达到O(n)了,但是还是Time Limit Exceded。可能是min()这个函数的复杂度比较高?
所以不用min()函数来判断。
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
max_profit = 0
a = [0] * len(prices)
if len(prices) == 0 or len(prices)==1:
return 0
else:
min_price = prices[0] if (prices[1] - prices[0] > 0) else prices[1]
for i in range(1,len(prices)):
if prices[i] < min_price:
min_price = prices[i]
a[i] = max(prices[i] - min_price,a[i-1])
max_profit = max(a[i],max_profit)
return max_profit
这个是AC的代码。要注意的是要处理好prices长度为0和1的情况。
if len(prices) == 0 or len(prices)==1:
这一句当时我是这么写的,虽然编译没有错,但python里没有这个用法。逻辑运算里用的是or 和and
if len(prices) == 0 | len(prices)==1:
还有python的三元运算符,a = b if c else d:
min_price = prices[0] if (prices[1] - prices[0] > 0) else prices[1]
在DISCUSS里有一个人的解法特别的巧妙。我理解了一下,也用Python:
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
max_profit = 0
final_profit = 0
for i in range(1,len(prices)):
max_profit += prices[i]-prices[i-1]
max_profit = max(0,max_profit)
final_profit = max(max_profit,final_profit)
return final_profit
这个解法都不需要考虑数组是0和1的情况。而且也是O(n)的时间复杂度,解释一下:
假设数组为[a,b,c,d,e,f,g],max_profit实的计算:
当i = 1:max_profit = b - a
当i = 2:(b - a) + (c - b) = c - a
当i = 3 :(b - a) + (c - b) + (d - c) = d - a
...
这是在开始默认price[0]为最小值,计算当前i与默认最小值的差值。
这一行,假如b - a < 0 也就是 b < a ,max_profit 置0,其实作用就是确定当前的最小值。
max_profit = max(0,max_profit)
也就是说,在接下来max_profit的累加中,b成为了最小值,计算
当i = 2 :(b - a)+ (c - b) = c - b
当i = 3 :(b - a) + (c - b) + (d - c) = d - b