Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 7e373a2

Browse files
committedJul 29, 2022
feat: add solutions to lc problem: No.2355
No.2355.Maximum Number of Books You Can Take
1 parent df14a92 commit 7e373a2

File tree

10 files changed

+664
-14
lines changed

10 files changed

+664
-14
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
# [2355. Maximum Number of Books You Can Take](https://leetcode.cn/problems/maximum-number-of-books-you-can-take)
2+
3+
[English Version](/solution/2300-2399/2355.Maximum%20Number%20of%20Books%20You%20Can%20Take/README_EN.md)
4+
5+
## 题目描述
6+
7+
<!-- 这里写题目描述 -->
8+
9+
<p>You are given a <strong>0-indexed</strong> integer array <code>books</code> of length <code>n</code> where <code>books[i]</code> denotes the number of books on the <code>i<sup>th</sup></code> shelf of a bookshelf.</p>
10+
11+
<p>You are going to take books from a <strong>contiguous</strong> section of the bookshelf spanning from <code>l</code> to <code>r</code> where <code>0 &lt;= l &lt;= r &lt; n</code>. For each index <code>i</code> in the range <code>l &lt;= i &lt; r</code>, you must take <strong>strictly fewer</strong> books from shelf <code>i</code> than shelf <code>i + 1</code>.</p>
12+
13+
<p>Return <em>the <strong>maximum</strong> number of books you can take from the bookshelf.</em></p>
14+
15+
<p>&nbsp;</p>
16+
<p><strong>Example 1:</strong></p>
17+
18+
<pre>
19+
<strong>Input:</strong> books = [8,5,2,7,9]
20+
<strong>Output:</strong> 19
21+
<strong>Explanation:</strong>
22+
- Take 1 book from shelf 1.
23+
- Take 2 books from shelf 2.
24+
- Take 7 books from shelf 3.
25+
- Take 9 books from shelf 4.
26+
You have taken 19 books, so return 19.
27+
It can be proven that 19 is the maximum number of books you can take.
28+
</pre>
29+
30+
<p><strong>Example 2:</strong></p>
31+
32+
<pre>
33+
<strong>Input:</strong> books = [7,0,3,4,5]
34+
<strong>Output:</strong> 12
35+
<strong>Explanation:</strong>
36+
- Take 3 books from shelf 2.
37+
- Take 4 books from shelf 3.
38+
- Take 5 books from shelf 4.
39+
You have taken 12 books so return 12.
40+
It can be proven that 12 is the maximum number of books you can take.
41+
</pre>
42+
43+
<p><strong>Example 3:</strong></p>
44+
45+
<pre>
46+
<strong>Input:</strong> books = [8,2,3,7,3,4,0,1,4,3]
47+
<strong>Output:</strong> 13
48+
<strong>Explanation:</strong>
49+
- Take 1 book from shelf 0.
50+
- Take 2 books from shelf 1.
51+
- Take 3 books from shelf 2.
52+
- Take 7 books from shelf 3.
53+
You have taken 13 books so return 13.
54+
It can be proven that 13 is the maximum number of books you can take.
55+
</pre>
56+
57+
<p>&nbsp;</p>
58+
<p><strong>Constraints:</strong></p>
59+
60+
<ul>
61+
<li><code>1 &lt;= books.length &lt;= 10<sup>5</sup></code></li>
62+
<li><code>0 &lt;= books[i] &lt;= 10<sup>5</sup></code></li>
63+
</ul>
64+
65+
## 解法
66+
67+
<!-- 这里可写通用的实现逻辑 -->
68+
69+
**方法一:单调栈 + 动态规划**
70+
71+
设 $dp[i]$ 表示以 $books[i]$ 结尾时能取走的书的最大数量。
72+
73+
若从 $i$ 到 $0$ 可以取成一个公差为 $1$ 的等差数列,那么 $dp[i]$ 可以直接通过等差数列求和算出。
74+
75+
若从 $i$ 到 $0$ 不能取成一个公差为 $-1$ 的等差数列,即这个规律在某个 $j$ 处断掉了($0 \le j \lt i$),那么一定有 $books[j] \lt books[i] - (i-j)$,也即 $books[j] - j \lt books[i] - i$,利用单调栈在新数组 $books[i] - i$ 的每个位置,找到左边第一个比它严格小的数的位置,可以求出符合题意的 $j$,此时 $dp[i]=dp[j] + \sum_{k=j+1}^{i} (books[k]-k)$。
76+
77+
答案为 $max(dp[i])$。
78+
79+
时间复杂度 $O(n)$。
80+
81+
<!-- tabs:start -->
82+
83+
### **Python3**
84+
85+
<!-- 这里可写当前语言的特殊实现逻辑 -->
86+
87+
```python
88+
class Solution:
89+
def maximumBooks(self, books: List[int]) -> int:
90+
nums = [v - i for i, v in enumerate(books)]
91+
n = len(nums)
92+
left = [-1] * n
93+
stk = []
94+
for i, v in enumerate(nums):
95+
while stk and nums[stk[-1]] >= v:
96+
stk.pop()
97+
if stk:
98+
left[i] = stk[-1]
99+
stk.append(i)
100+
ans = 0
101+
dp = [0] * n
102+
dp[0] = books[0]
103+
for i, v in enumerate(books):
104+
j = left[i]
105+
cnt = min(v, i - j)
106+
u = v - cnt + 1
107+
s = (u + v) * cnt // 2
108+
dp[i] = s + (0 if j == -1 else dp[j])
109+
ans = max(ans, dp[i])
110+
return ans
111+
```
112+
113+
### **Java**
114+
115+
<!-- 这里可写当前语言的特殊实现逻辑 -->
116+
117+
```java
118+
class Solution {
119+
public long maximumBooks(int[] books) {
120+
int n = books.length;
121+
int[] nums = new int[n];
122+
for (int i = 0; i < n; ++i) {
123+
nums[i] = books[i] - i;
124+
}
125+
int[] left = new int[n];
126+
Arrays.fill(left, -1);
127+
Deque<Integer> stk = new ArrayDeque<>();
128+
for (int i = 0; i < n; ++i) {
129+
while (!stk.isEmpty() && nums[stk.peek()] >= nums[i]) {
130+
stk.pop();
131+
}
132+
if (!stk.isEmpty()) {
133+
left[i] = stk.peek();
134+
}
135+
stk.push(i);
136+
}
137+
long ans = 0;
138+
long[] dp = new long[n];
139+
dp[0] = books[0];
140+
for (int i = 0; i < n; ++i) {
141+
int j = left[i];
142+
int v = books[i];
143+
int cnt = Math.min(v, i - j);
144+
int u = v - cnt + 1;
145+
long s = (long) (u + v) * cnt / 2;
146+
dp[i] = s + (j == -1 ? 0 : dp[j]);
147+
ans = Math.max(ans, dp[i]);
148+
}
149+
return ans;
150+
}
151+
}
152+
```
153+
154+
### **C++**
155+
156+
```cpp
157+
using ll = long long;
158+
159+
class Solution {
160+
public:
161+
long long maximumBooks(vector<int>& books) {
162+
int n = books.size();
163+
vector<int> nums(n);
164+
for (int i = 0; i < n; ++i) nums[i] = books[i] - i;
165+
vector<int> left(n, -1);
166+
stack<int> stk;
167+
for (int i = 0; i < n; ++i)
168+
{
169+
while (!stk.empty() && nums[stk.top()] >= nums[i]) stk.pop();
170+
if (!stk.empty()) left[i] = stk.top();
171+
stk.push(i);
172+
}
173+
vector<ll> dp(n);
174+
dp[0] = books[0];
175+
ll ans = 0;
176+
for (int i = 0; i < n; ++i)
177+
{
178+
int v = books[i];
179+
int j = left[i];
180+
int cnt = min(v, i - j);
181+
int u = v - cnt + 1;
182+
ll s = 1ll * (u + v) * cnt / 2;
183+
dp[i] = s + (j == -1 ? 0 : dp[j]);
184+
ans = max(ans, dp[i]);
185+
}
186+
return ans;
187+
}
188+
};
189+
```
190+
191+
### **Go**
192+
193+
```go
194+
func maximumBooks(books []int) int64 {
195+
n := len(books)
196+
nums := make([]int, n)
197+
left := make([]int, n)
198+
for i, v := range books {
199+
nums[i] = v - i
200+
left[i] = -1
201+
}
202+
stk := []int{}
203+
for i, v := range nums {
204+
for len(stk) > 0 && nums[stk[len(stk)-1]] >= v {
205+
stk = stk[:len(stk)-1]
206+
}
207+
if len(stk) > 0 {
208+
left[i] = stk[len(stk)-1]
209+
}
210+
stk = append(stk, i)
211+
}
212+
dp := make([]int, n)
213+
dp[0] = books[0]
214+
ans := 0
215+
for i, v := range books {
216+
j := left[i]
217+
cnt := min(v, i-j)
218+
u := v - cnt + 1
219+
s := (u + v) * cnt / 2
220+
dp[i] = s
221+
if j != -1 {
222+
dp[i] += dp[j]
223+
}
224+
ans = max(ans, dp[i])
225+
}
226+
return int64(ans)
227+
}
228+
229+
func max(a, b int) int {
230+
if a > b {
231+
return a
232+
}
233+
return b
234+
}
235+
236+
func min(a, b int) int {
237+
if a < b {
238+
return a
239+
}
240+
return b
241+
}
242+
```
243+
244+
### **TypeScript**
245+
246+
```ts
247+
248+
```
249+
250+
### **...**
251+
252+
```
253+
254+
```
255+
256+
<!-- tabs:end -->
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)