最后更新:2022-07-29 03:50:59 手机定位技术交流文章
在前面的文章 你见过这种动态编程吗--状态机动态编程的库存问题 我们已推出两项基本股票发行,并且对 简要介绍了国家机器动态规划,以及状态机器中的状态如何转换,但前两个问题中的州数相对较小,每个人都很难理解国家机器的意义,在 本文 讨论 的 两 个 问题 中, 国家 的 数目 仍然 相当 大,因此对于大家深入理解状态机动态规划可能会好一点。
给定一个数组,它的第一个元素是给定的股票在第一天的价格。设计一个算法来计算你能获得的最大利润.你可以做到两个交易。注:你不能同时参与多个交易(你必须在再次购买股票之前卖掉股票)。
示例1
输入:价格 = [3,3,5,0,0,3,1,4]
输出:6
说明:4日购买(股票价格=0),於第六日(股票价格=3)出售,交换机可以赚取利润=3-0=3。随后,7日购买(股票价格=1),在第 8 天 (股票价格 = 4)的时候卖出,交易是盈利性的 = 4-1 = 3.
示例2
输入:价格 = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。注意你不能连续第1日和第2日购买股票,之后再将它们卖出。因为这属于同时参与多个交易,你必须卖掉股票才能再买.
这道题目跟之前的两道题目不同之处在于,在上篇文章当中的两道题要么是能够购买一次,要么能够购买无数次,而在本道题目当中只能够购买两次,在这种情况下我们应该如何定义各种状态呢?
在这一主题中,我们还表达了二维群的状态,即dp[N][5]5意味着我们有5个州。dp[N][i]表示第N天的第i个状态能够多大的收益!(为了方便下面介绍,假设一天有一个股票,dp[N][]九日状态与九日库存状态相符.
dp[N][0],表示第N天一次买入和卖出的操作都没有过,那么dp[N][0] = dp[N - 1][0]正如上天那样,没有股票的买卖,事实上,也可以指向dp[N][0] = 0因为我们不经营,我们的利润肯定是零的。dp[N][1],表示第N天已经进行过第一次买入,这个买入可以是在第N天进行买入,也可以在前面N-1天买入,然后在第N天保持状态。dp[N][0] - prices[i]因为根据上述分析dp[N][0] = 0,那么直接让dp[N][1] = -prices[i]即可。dp[N][1] = dp[N - 1][1]。dp[N][2],表示第N天已经进行过第一次卖出,这个状态可以是在第N天进行卖出,也可以是在前面N-1天已经卖出,然后在第N天保持状态prices[i],加上前N-1的第一天的收入,即dp[N][2] = dp[N - 1][1] + prices[i]。dp[N][2] = dp[N - 1][2]。dp[N][3],表示第N天已经进行过第二次买入,这个状态可以是在第N天进行买入,也可以是在前面N-1天买入,然后在第N天保持状态。-prices[i]加上在N-1日前一天购买和销售的收入,即:dp[N][3] = dp[N - 1][2] - prices[i]。dp[N][3] = dp[N - 1][3]。dp[N][4],表示第N天已经进行过第二次卖出,这个状态可以是在第N天进行买入,也可以是在前面N-1天卖出,然后在第N天保持状态。prices[i]加上过去N-1天两次购买和一次销售的收益dp[N][3],那么dp[N][4] = dp[N - 1][3] + prices[i]。dp[N][4] = dp[N-1][4]。根据上述分析,我们可以得到以下状态机器(状态转移图):

相信还是不相信,你应该能够理解为什么这种动态规划叫做国家机器动态规划。因为在这个动态规划中有许多数据状态,我们需要仔细分析,清楚地分析如何将内部状态转移,然后分析不同国家之间的转移关系,这个模型非常类似于状态机器,因此, 它被称为状态机器动态规划.
如果一个股票的交易日数是总数N天,那么我们最终需要找到的结果是dp[N][4],表示第N天已经买入卖出2次,将两次使用的机会都是用完了,为什么我们最终的结果是dp[N][4]呢?你怀疑我买一次,卖一次,能得到最大回报吗?我们被允许在同一天购买和出售股票,同一天,购买和出售股票的收益为零,所以它不会影响最终的结果,因此买入卖出一次最终也可以转移到买入卖出两次(其中一次在同一天买入和卖出即可,当我们初始化一组数字时,我们需要购买和销售数次(见下面初始化一组数字的分析)。因此我们最终需要返回的结果是dp[N][4]。
根据上面的分析,我们知道从上面的图中我们可以看到到dp[N][4]这样做有两种方法,我们应该选择一个比另一个更有价值的方法,即:dp[N][4] = max(dp[N - 1][4], dp[N - 1][3] + prices[i]);,而dp[N - 1][4]有两种转移方式, 我们应该选择较大的.dp[N - 1][3]有两种传输方式,所以它也应该选择一个比两者大值的值,即:dp[N][3] = max(dp[N - 1][3], dp[N - 1][2] - prices[N]);我们能得到的转移方程的其他状态方程,每个数据在选择转移后具有最高的值,最终我们的转移方程如下:
解决动态规划问题通常的步骤如下:
dp,即我们需要寻找dp分析需要用一系列纬度来表达具体的状态。我们已经完成前段的两个步骤,现在我们需要开始对集合进行初始化。 第一天我们不能买进股票,所以第一天我们的利润是零dp[0][0] = 0我们还可以买份股票dp[0][1] = -prices[0]我们可以买一个,然后再卖它,这意味着不买,因为价格是同一天的dp[0][2] = 0我们也可以买两次,即先买,然后卖,然后买dp[0][3] = -prices[0]同样,我们也可以购买和销售两次,最终回报为0,即dp[0][4] = 0。
为了总结上述分析,我们的初始化代码如下:
根据国家转移方程,我们知道i天依赖于第i-1天上的数据, 所以我们穿过以便从前到后穿过.
上述代码的时间和空间复杂性分别是 O ( n ) O(n) O ( n ) 和 O ( n ) O(n) O ( n ) 。
事实上,我们可以使用单行阵列来优化,优化代码如下:
让我们简要地分析一下上面的代码为什么有效:
比如现在i=3我马上更新它dp数组还是i=2如果以二维阵列表示,当前单行阵列的状态dp[i]等于二维阵列中的数据dp[2][i]如果我们现在需要更新dp[3][2]基于二维群动态传递方程,我们需要二维群的第二行数据dp[2][2]然而,目前单行组的数据还没有更新,这意味着dp[2]等于dp[2][2](前面的dp表示一个单行组,其次是dp表表示二维数组的dp),所以这是从前一个状态的数据,所以没有问题更新。
根据上述国家转移方程,我们知道dp[3][2]依赖于dp[2][1],而dp[2][1]相当于dp[1]但是下面的代码中,我们正在更新dp[2]之前dp[1]已更新,即:dp[1]它已经在第三排,即.dp[1] = dp[3][1]更新需要第二个行, 因此这不是这种情况.
那么为什么上面的代码工作?
dp[1]是从上一行的dp[1]这就是我们的想法。dp[2]在前行(第二行)的状态中使用dp[1],因为当前线的状态(行3)dp[1]和第2行的dp[1]相等。dp[1]是从dp[0] - prices[3]被转移,然后在这个句子里dp[2] = Math.max(dp[2], dp[1] + prices[3]);当中,如果选择的是dp[2]没什么关系,因为他dp[1]没关系,如果你选择dp[1] + prices[3],那么也没关系因为dp[1]减去了prices[3],这一加一减相当于没有收益,这并不影响最后的结果,因为这一卖一买都是在今天完成的,而对最终结果产生影响的肯定是在前面已经买入的操作(比如第2行的dp[1]就表示在之前进行第一次买入),而不会是在今天的买入,理解这一点就可以理解上的代码了。经过上述优化后,空间复杂度变为 O ( 1 ) O(1) O ( 1 ) 。
给出一个整数的价格集,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格。设计一个算法来计算你能获得的最大利润.你可以做最多k交易。注:你不能同时参与多个交易(你必须在再次购买股票之前卖掉股票)。
示例1
输入:k=2,价格=[2,4,1]
输出:2
解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
示例2
输入:k=2,价格= [3,2,6,5,0,3]
输出:7
解释:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 交换机可以赚取利润=3-0=3。
这个问题和本文当中的第一个问题其实差不多,只不过上面的问题是最多完成两笔交易,而在这个问题当中是最多可以完成k问题与上文问题的一般化相等,让我们分析上文问题的动态转移公式:
上述公式由以下公式表达:
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
−
1
]
[
j
−
1
]
±
p
r
i
c
e
s
[
i
]
)
;
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] pm prices[i]);
d
p
[
i
]
[
j
]
=
ma
x
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
−
1
]
[
j
−
1
]
±
p
r
i
ces
[
i
])
;
现在我们将宣传这个问题:
状态表示
dp[i][0]没有人可以买或卖。dp[i][2 * k - 1]表示第k次买入。k次买入这个状态。i-1天已经有k下次你买东西时,你将保持原来的dp[i][2 * k - 1] = dp[i - 1][2 * k - 1]。i-1天已经有k-1如果你买和卖, 那么你需要买, 即.dp[i][2 * k - 1] = dp[i - 1][2 * k - 2]- prices[i]。dp[i][2 * k]表示第k次卖出。i-1天已经有k下次卖完, 就跟以前一样了.dp[i][2 * k] = dp[i - 1][2 * k]。i-1天已经有k下一次购买, 然后你需要做购买, 即.dp[i][2 * k] = dp[i - 1][2 * k - 1] + prices[i]。根据上述分析,状态转移方程如下:j是偶数):
最终我们需要返回的结果是dp[N][2 * k]。
数组初始化
-pirces[0],所有的卖出状态的价值都是0,因为买入之后再卖出就相当于没有买卖一样。本文主要介绍了另外两个库存问题,在这两个股票发行中有许多州,国家间的转变也更加复杂,经过仔细分析上述两个问题的状态变换后,相信你已经理解了状态机的动态规划,这种更复杂的状态之间的变化称为状态机器动态规划。这个问题通常比分析更加复杂。
更多有趣的内容收集可以在项目上访问: https://github.Chang-LeHung/CSCore
对公众的注意: 研究者在任何地方都可以了解计算机(Java、Python、计算机系统、算法和数据结构)。
本文由 在线网速测试 整理编辑,转载请注明出处。