有一个数组,元素是每天股票的价格
假设你只允许交易一次(买入和卖出股票),设计一个算法可以获取最大收益。
比如:
Input: [7, 1, 5, 3, 6, 4]
Output: 5
max. difference = 6-1 = 5 (not 7-1 = 6, 卖出的价格要大于买入的价格,要买入之后才可以卖出)
Input: [7, 6, 4, 3, 1]
Output: 0
在这个例子中没有交易,因为max profit = 0.
动态规划(DP)
设d(i)为前i个元素的最大收益,k为前i个元素中最小的数
Input: [7, 1, 5, 3, 6, 4] 则有:
d(1) = 0 k=7
d(2) = 0 1
d(4) = 4 (3-k=2)<(d(3)=4) 3>k k=1
d(5) = 5 (6-k=5)>(d(4)=4) 6>k k=1
d(6) = 5 (4-k=3)<(d(5)=5) 4>k k=1
状态:d(i) i个元素的最大收益
状态转移方程:d(i) = max(a[i]-k,d(i-1))
用递推思想来实现代码如下:
func maxProfit(_ prices: [Int]) -> Int {
var minPrice = Int.max
var maxProfit = 0
for price in prices {
minPrice = min(minPrice, price)
maxProfit = max(maxProfit, price-minPrice)
}
return maxProfit
}
分治算法(Divide and Conquer technique):
可以采用二分法求解,思路如下:
数组A,长度为n,d(A,i,j)返回(maxProfit,minPrice,maxPrice),分别为数组A中元素i...j的最大收益,最小价格和最大价格。由此可得:
m = i + (i+j)/2
d(A,i,j).maxProfit = Max(d(A,m+1,j).maxPrice-d(A,i,m).minPrice, d(A,i,m).maxProfit, d(A,m+1,j).maxProfit)
d(A,i,j).minPrice = Min(d(A,m+1,j).minPrice, d(A,i,m).minPrice)
d(A,i,j).maxPrice = Max(d(A,m+1,j).maxPrice, d(A,i,m).maxPrice)
代码如下:
func maxProfit2(_ prices: [Int]) -> Int {
return prices.count == 0 ? 0 : helper(prices, i: 0, j: prices.count-1).maxProfit
}
func helper(_ prices: [Int], i: Int, j: Int) -> (maxProfit: Int, minPrice: Int, maxPrice: Int) {
var result = (maxProfit: 0, minPrice: prices[i], maxPrice: prices[j])
if i == j {
return result
}
let m = i + (j - i) / 2
let leftResult = helper(prices, i: i, j: m)
let rightResult = helper(prices, i: m+1, j: j)
result.maxProfit = max(max(rightResult.maxPrice - leftResult.minPrice, leftResult.maxProfit), rightResult.maxProfit)
result.minPrice = min(leftResult.minPrice, rightResult.minPrice)
result.maxPrice = max(leftResult.maxPrice, rightResult.maxPrice)
return result
}