我花了大约3个小时来解决这个问题,但是我无法理解两行代码:
b[j] = _max(b[j], s[j] - prices[i]);
s[j + 1] = _max(s[j + 1], b[j] + prices[i]);
以下代码是DP解决方案的问题是: 买卖股票的最佳时间
假设您有一个数组,第i个元素是第i天给定股票的价格。
设计算法以找到最大利润。您最多可以完成k笔交易。
注意: 您可能不能同时进行多项交易(例如,必须先出售股票才能再次购买)。
示例1:
输入:[2,4,1],k = 2
输出:2
说明:在第1天买入(价格= 2)并在第2天卖出(价格= 4),利润= 4-2 = 2。
示例2:
输入:[3,2,6,5,0,3],k = 2
输出:7
说明:在第2天购买(价格= 2)并在第3天出售(价格= 6),利润= 6-2 = 4。 然后在第5天买入(价格= 0)并在第6天卖出(价格= 3),利润= 3-0 = 3。
int _max(int a, int b) {
return a > b ? a : b;
}
int all_profits(int* prices, int pricesSize) {
int i, d, p;
p = 0;
for (i = 1; i < pricesSize; i ++) {
d = prices[i] - prices[i - 1];
p = d > 0 ? p + d : p; // get it as long as it is a profit!
}
return p;
}
int maxProfit(int k, int* prices, int pricesSize) {
int *b, *s, *buff, i, j, p;
if (pricesSize < 2) return 0;
if (k >= pricesSize / 2) return all_profits(prices, pricesSize);
buff = malloc((2 * k + 1) * sizeof(int));
//assert(buff);
b = &buff[0];
s = &buff[k];
for (i = 0; i < k; i ++) {
b[i] = 0x80000000; // min integer
s[i] = 0;
}
s[k] = 0;
for (i = 0; i < pricesSize; i ++) {
for (j = 0; j < k; j ++) {
// profit on buy is current buy or last sale minus today's price
b[j] = _max(b[j], s[j] - prices[i]);
// profit on sale is current sale or last buy plus today's price
s[j + 1] = _max(s[j + 1], b[j] + prices[i]);
}
}
p = s[k];
free(buff);
return p;
}
除了开头提到的两行内容,我了解所有代码:
b[j] = _max(b[j], s[j] - prices[i]);
的MAX,所以购买价格不应该是最低的吗?为什么b [j]这两个事物的最大值? s [j]-价格[i]是什么?s[j + 1] = _max(s[j + 1], b[j] + prices[i]);
在此表达式中b [j] + price [i]是什么意思? for (j = 0; j < k; j ++) {
?我花了很多时间(3个小时)考虑此解决方案并将其与其他DP问题进行比较,但是没有运气。我将它与最长增长子序列DP问题进行了比较,以及如何“让length(k)表示终止于位置k的最长增长子序列的长度”,并尝试将该逻辑应用于此处的数组,但是没有运气。
谢谢您的帮助。
答案 0 :(得分:2)
请考虑我们希望将每个价格(或一天)视为购买日或销售日,以得出最佳选择。 b
列表将每天视为buy
天,并将s
列表视为sell
天。现在我们只是实现逻辑。可能有点令人困惑的是,由于s
是在j + 1
更新的,对于s
列表,j
是前一天。
价格为k
的最佳第i
个购买日是我们已经拥有的第k
个购买日或我们购买的等于(k-1)
的购买日自我们刚买进以来,第一个卖出天数(即令人困惑的s[j]
)减去买入价!
b[j] = _max(b[j], s[j] - prices[i]);
价格为k
的第i
个最佳买入日是我们第k
个销售日所拥有的,或者是第k
个买入日最好的(因为第k
条交易同时有买和卖)加上今天的价格,因为我们只是通过卖出股票而赚了!
s[j + 1] = _max(s[j + 1], b[j] + prices[i]);
根据OP的请求,下面是一个示例:[5, 20, 15, 100, 35] k = 2
。
b represents the most profit at
the jth buy considering prices up to i:
max(b[j], s[j] - prices[i])
s represents the most profit at
the jth sell (index j+1 in s) considering prices up to i:
max(s[j + 1], b[j] + prices[i])
note that when j = 0, s[j] (the sell before the first buy)
is always 0
prices[0]:
j: 0 1
b: -5 -5 // max(-Inf, 0 - 5), max(-Inf, 0 - 5)
s: 0 0 // max(0, -5 + 5), max(0, -5 + 5)
prices[1]:
j: 0 1
b: -5 -5 // max(-5, 0 - 20), max(-5, 15 - 20)
s: 15 15 // max(0, -5 + 20), max(0, -5 + 20)
prices[2]:
j: 0 1
b: -5 0 // max(-5, 0 - 15), max(-5, 15 - 15)
s: 15 15 // max(15, -5 + 15), max(15, 0 + 15)
prices[3]:
j: 0 1
b: -5 0 // max(-5, 0 - 100), max(0, 0 - 100)
s: 95 100 // max(15, -5 + 100), max(15, 0 + 100)
prices[4]:
j: 0 1
b: -5 60 // max(-5, 0 - 35), max(0, 95 - 35)
s: 95 100 // max(95, -5 + 35), max(100, 60 + 35)