Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7e373a2

Browse files
committed
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
Lines changed: 256 additions & 0 deletions
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 -->

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /