forked from wisdompeak/LeetCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9b94c3e
commit 6a27725
Showing
1 changed file
with
13 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
### 2355.Maximum-Number-of-Books-You-Can-Take | ||
|
||
我们令dp[i]表示以i为结尾的区间所能获得的最大值。显然在这个区间里,位置i处一定会取满books[i]。 | ||
|
||
然后在dp[i]的前提下,我们考察i-1的位置。如果`books[i-1]>=books[i]-1`,那么意味着无法取满books[i-1],且显然,该位置的取值决定于`books[i]-1`. 类似地,在i-2处,如果`books[i-2]>=books[i]-2`,那么该位置能取的最大值是由books[i]-2决定的。依次往前类推,我们会经历一段逐个减1的等差数列。直至我们发现某处`books[j]<books[i]-(i-j)`,那么我们势必会在j处取books[j],于是自然就有`dp[i] = dp[j] + 长度为i-j且公差为1的等差数列之和`. | ||
|
||
那么对于每个i,我们是否都要靠上述的方法逐一回溯之前的index来确定j的位置呢?实际上,当我们针对某个i确定了j之后,books[j+1:i-1]内的这些元素都可以舍弃不看了。因为未来的任何dp[k](其中k>i)如果依赖于dp[i],那么即`dp[k] = dp[i] + [i+1:k]的等差数列之和`,不需要再计算任何i之前的东西。相反,如果dp[k]不依赖于dp[i],那么意味着在i的位置上没有取满,自然[j+1:i-1]区间内也不会取满(因为这个区间的books值都高于以books[i]开始从后往前的等差序列)。 | ||
|
||
所以我们就可以设计一个单调栈。当考察新元素books[i]时,对于栈顶元素j,如果`books[j]>=books[i]-(i-j)`的话,就可以不断退栈: | ||
1. 如果剩余有栈顶元素j,那么`dp[i] = dp[j] + area`,其中area是长度为`L = i-j`,最后一个元素是books[i],公差为1的等差数列之和。于是根据等差数列的求和公式`area = (books[i]-L+1 + books[i]) * L /2`. | ||
2. 如果剩余没有栈顶元素,那么直接有`dp[i] = area`,其中area(可能)是长度为i+1,最后一个元素是books[i],公差为1的等差数列之和。特别注意,等差数列的第一个元素不能小于1。所以,这个等差数列的实际长度应该是`L = min(i+1, heights[i])`. 于是根据等差数列的求和公式`area = (books[i]-L+1 + books[i]) * L /2`. | ||
|
||
最后返回的是全局dp[i]的最大值。 |