Skip to content

Commit 4d8e387

Browse files
authored
feat: add solutions to lcp problems: No.77,78 (#1218)
* No.77.符文储备 * No.78.城墙防线
1 parent 0a6a47a commit 4d8e387

12 files changed

+454
-2
lines changed

lcp/LCP 77. 符文储备/README.md

+84-1
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,105 @@
3838

3939
<!-- 这里可写通用的实现逻辑 -->
4040

41+
**方法一:排序**
42+
43+
我们可以将符文按照魔力值从小到大排序,然后使用双指针维护一个滑动窗口,使得滑动窗口中的任意相邻的两块符文之间的魔力值相差不超过,找出满足条件的最大窗口长度即可。
44+
45+
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组 $runes$ 的长度。
46+
4147
<!-- tabs:start -->
4248

4349
### **Python3**
4450

4551
<!-- 这里可写当前语言的特殊实现逻辑 -->
4652

4753
```python
48-
54+
class Solution:
55+
def runeReserve(self, runes: List[int]) -> int:
56+
runes.sort()
57+
ans = i = 0
58+
for j, x in enumerate(runes):
59+
if j and runes[j] - runes[j - 1] > 1:
60+
i = j
61+
else:
62+
ans = max(ans, j - i + 1)
63+
return ans
4964
```
5065

5166
### **Java**
5267

5368
<!-- 这里可写当前语言的特殊实现逻辑 -->
5469

5570
```java
71+
class Solution {
72+
public int runeReserve(int[] runes) {
73+
Arrays.sort(runes);
74+
int ans = 0;
75+
for (int i = 0, j = 0; j < runes.length; ++j) {
76+
if (j > 0 && runes[j] - runes[j - 1] > 1) {
77+
i = j;
78+
} else {
79+
ans = Math.max(ans, j - i + 1);
80+
}
81+
}
82+
return ans;
83+
}
84+
}
85+
```
86+
87+
### **C++**
88+
89+
```cpp
90+
class Solution {
91+
public:
92+
int runeReserve(vector<int>& runes) {
93+
sort(runes.begin(), runes.end());
94+
int ans = 0;
95+
for (int i = 0, j = 0; j < runes.size(); ++j) {
96+
if (j && runes[j] - runes[j - 1] > 1) {
97+
i = j;
98+
} else {
99+
ans = max(ans, j - i + 1);
100+
}
101+
}
102+
return ans;
103+
}
104+
};
105+
```
106+
107+
### **Go**
108+
109+
```go
110+
func runeReserve(runes []int) (ans int) {
111+
sort.Ints(runes)
112+
i := 0
113+
for j, x := range runes {
114+
if j > 0 && x-runes[j-1] > 1 {
115+
i = j
116+
} else if t := j - i + 1; ans < t {
117+
ans = t
118+
}
119+
}
120+
return
121+
}
122+
```
56123

124+
### **TypeScript**
125+
126+
```ts
127+
function runeReserve(runes: number[]): number {
128+
runes.sort((a, b) => a - b);
129+
let ans = 0;
130+
let i = 0;
131+
for (let j = 0; j < runes.length; ++j) {
132+
if (j > 0 && runes[j] - runes[j - 1] > 1) {
133+
i = j;
134+
} else {
135+
ans = Math.max(ans, j - i + 1);
136+
}
137+
}
138+
return ans;
139+
}
57140
```
58141

59142
### **...**

lcp/LCP 77. 符文储备/Solution.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Solution {
2+
public:
3+
int runeReserve(vector<int>& runes) {
4+
sort(runes.begin(), runes.end());
5+
int ans = 0;
6+
for (int i = 0, j = 0; j < runes.size(); ++j) {
7+
if (j && runes[j] - runes[j - 1] > 1) {
8+
i = j;
9+
} else {
10+
ans = max(ans, j - i + 1);
11+
}
12+
}
13+
return ans;
14+
}
15+
};

lcp/LCP 77. 符文储备/Solution.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
func runeReserve(runes []int) (ans int) {
2+
sort.Ints(runes)
3+
i := 0
4+
for j, x := range runes {
5+
if j > 0 && x-runes[j-1] > 1 {
6+
i = j
7+
} else if t := j - i + 1; ans < t {
8+
ans = t
9+
}
10+
}
11+
return
12+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Solution {
2+
public int runeReserve(int[] runes) {
3+
Arrays.sort(runes);
4+
int ans = 0;
5+
for (int i = 0, j = 0; j < runes.length; ++j) {
6+
if (j > 0 && runes[j] - runes[j - 1] > 1) {
7+
i = j;
8+
} else {
9+
ans = Math.max(ans, j - i + 1);
10+
}
11+
}
12+
return ans;
13+
}
14+
}

lcp/LCP 77. 符文储备/Solution.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class Solution:
2+
def runeReserve(self, runes: List[int]) -> int:
3+
runes.sort()
4+
ans = i = 0
5+
for j, x in enumerate(runes):
6+
if j and runes[j] - runes[j - 1] > 1:
7+
i = j
8+
else:
9+
ans = max(ans, j - i + 1)
10+
return ans

lcp/LCP 77. 符文储备/Solution.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
function runeReserve(runes: number[]): number {
2+
runes.sort((a, b) => a - b);
3+
let ans = 0;
4+
let i = 0;
5+
for (let j = 0; j < runes.length; ++j) {
6+
if (j > 0 && runes[j] - runes[j - 1] > 1) {
7+
i = j;
8+
} else {
9+
ans = Math.max(ans, j - i + 1);
10+
}
11+
}
12+
return ans;
13+
}

lcp/LCP 78. 城墙防线/README.md

+166-1
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,187 @@
4646

4747
<!-- 这里可写通用的实现逻辑 -->
4848

49+
**方法一:二分查找**
50+
51+
我们注意到,如果一个膨胀值 $x$ 满足条件,那么所有小于 $x$ 的值也都满足条件,这存在着单调性。因此我们可以使用二分查找的方法,找到最大的满足条件的膨胀值。
52+
53+
我们定义二分查找的左边界 $left=0$, $right=rampart[1][0]-rampart[0][1]+rampart[2][0]-rampart[1][1]$,其中 $rampart[i][0]$ 表示第 $i$ 段城墙的左端点,$rampart[i][1]$ 表示第 $i$ 段城墙的右端点。
54+
55+
接下来,我们开始进行二分查找。每一次,我们求出当前的中间值 $mid$,并判断其是否满足条件。如果满足条件,那么我们就将左边界 $left$ 更新为 $mid$,否则将右边界 $right$ 更新为 $mid-1$。在二分查找结束后,我们返回左边界 $left$ 即可。
56+
57+
那么问题的关键在于如何判断一个值 $w$ 是否满足条件。显然,我们可以用贪心的策略,每次先尽可能往左膨胀,如果还有剩余的膨胀值,再往右膨胀,如果在向右膨胀的过程中,发生了重叠,那么说明当前的膨胀值 $w$ 不满足条件,直接返回 `false` 即可。否则,遍历结束,返回 `true`
58+
59+
时间复杂度 $O(n \times \log M)$,其中 $n$ 和 $M$ 分别是数组 $rampart$ 的长度和二分查找的右边界,本题中右边界最大为 $range=rampart[1][0]-rampart[0][1]+rampart[2][0]-rampart[1][1]$。空间复杂度 $O(1)$。
60+
4961
<!-- tabs:start -->
5062

5163
### **Python3**
5264

5365
<!-- 这里可写当前语言的特殊实现逻辑 -->
5466

5567
```python
56-
68+
class Solution:
69+
def rampartDefensiveLine(self, rampart: List[List[int]]) -> int:
70+
def check(w: int) -> bool:
71+
last = rampart[0][1]
72+
for i in range(1, len(rampart) - 1):
73+
x, y = rampart[i]
74+
a = x - last
75+
b = max(w - a, 0)
76+
if y + b > rampart[i + 1][0]:
77+
return False
78+
last = y + b
79+
return True
80+
81+
left, right = 0, rampart[1][0] - rampart[0][1] + rampart[2][0] - rampart[1][1]
82+
while left < right:
83+
mid = (left + right + 1) >> 1
84+
if check(mid):
85+
left = mid
86+
else:
87+
right = mid - 1
88+
return left
5789
```
5890

5991
### **Java**
6092

6193
<!-- 这里可写当前语言的特殊实现逻辑 -->
6294

6395
```java
96+
class Solution {
97+
private int[][] rampart;
98+
99+
public int rampartDefensiveLine(int[][] rampart) {
100+
this.rampart = rampart;
101+
int left = 0, right = rampart[1][0] - rampart[0][1] + rampart[2][0] - rampart[1][1];
102+
while (left < right) {
103+
int mid = (left + right + 1) >> 1;
104+
if (check(mid)) {
105+
left = mid;
106+
} else {
107+
right = mid - 1;
108+
}
109+
}
110+
return left;
111+
}
112+
113+
private boolean check(int w) {
114+
int last = rampart[0][1];
115+
for (int i = 1; i < rampart.length - 1; ++i) {
116+
int x = rampart[i][0], y = rampart[i][1];
117+
int a = x - last;
118+
int b = Math.max(w - a, 0);
119+
if (y + b > rampart[i + 1][0]) {
120+
return false;
121+
}
122+
last = y + b;
123+
}
124+
return true;
125+
}
126+
}
127+
```
128+
129+
### **C++**
130+
131+
```cpp
132+
class Solution {
133+
public:
134+
int rampartDefensiveLine(vector<vector<int>>& rampart) {
135+
int left = 0, right = rampart[1][0] - rampart[0][1] + rampart[2][0] - rampart[1][1];
136+
auto check = [&](int w) {
137+
int last = rampart[0][1];
138+
for (int i = 1; i < rampart.size() - 1; ++i) {
139+
int x = rampart[i][0], y = rampart[i][1];
140+
int a = x - last;
141+
int b = max(w - a, 0);
142+
if (y + b > rampart[i + 1][0]) {
143+
return false;
144+
}
145+
last = y + b;
146+
}
147+
return true;
148+
};
149+
150+
while (left < right) {
151+
int mid = (left + right + 1) >> 1;
152+
if (check(mid)) {
153+
left = mid;
154+
} else {
155+
right = mid - 1;
156+
}
157+
}
158+
return left;
159+
}
160+
};
161+
```
162+
163+
### **Go**
164+
165+
```go
166+
func rampartDefensiveLine(rampart [][]int) int {
167+
check := func(w int) bool {
168+
last := rampart[0][1]
169+
for i := 1; i < len(rampart)-1; i++ {
170+
x, y := rampart[i][0], rampart[i][1]
171+
a := x - last
172+
b := max(w-a, 0)
173+
if y+b > rampart[i+1][0] {
174+
return false
175+
}
176+
last = y + b
177+
}
178+
return true
179+
}
180+
181+
left, right := 0, rampart[1][0]-rampart[0][1]+rampart[2][0]-rampart[1][1]
182+
for left < right {
183+
mid := (left + right + 1) >> 1
184+
if check(mid) {
185+
left = mid
186+
} else {
187+
right = mid - 1
188+
}
189+
}
190+
return left
191+
}
192+
193+
func max(a, b int) int {
194+
if a > b {
195+
return a
196+
}
197+
return b
198+
}
199+
```
64200

201+
### **TypeScript**
202+
203+
```ts
204+
function rampartDefensiveLine(rampart: number[][]): number {
205+
const check = (w: number): boolean => {
206+
let last = rampart[0][1];
207+
for (let i = 1; i < rampart.length - 1; ++i) {
208+
const [x, y] = rampart[i];
209+
const a = x - last;
210+
const b = Math.max(w - a, 0);
211+
if (y + b > rampart[i + 1][0]) {
212+
return false;
213+
}
214+
last = y + b;
215+
}
216+
return true;
217+
};
218+
let left = 0;
219+
let right = rampart[1][0] - rampart[0][1] + rampart[2][0] - rampart[1][1];
220+
while (left < right) {
221+
const mid = (left + right + 1) >> 1;
222+
if (check(mid)) {
223+
left = mid;
224+
} else {
225+
right = mid - 1;
226+
}
227+
}
228+
return left;
229+
}
65230
```
66231

67232
### **...**

lcp/LCP 78. 城墙防线/Solution.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
class Solution {
2+
public:
3+
int rampartDefensiveLine(vector<vector<int>>& rampart) {
4+
int left = 0, right = rampart[1][0] - rampart[0][1] + rampart[2][0] - rampart[1][1];
5+
auto check = [&](int w) {
6+
int last = rampart[0][1];
7+
for (int i = 1; i < rampart.size() - 1; ++i) {
8+
int x = rampart[i][0], y = rampart[i][1];
9+
int a = x - last;
10+
int b = max(w - a, 0);
11+
if (y + b > rampart[i + 1][0]) {
12+
return false;
13+
}
14+
last = y + b;
15+
}
16+
return true;
17+
};
18+
19+
while (left < right) {
20+
int mid = (left + right + 1) >> 1;
21+
if (check(mid)) {
22+
left = mid;
23+
} else {
24+
right = mid - 1;
25+
}
26+
}
27+
return left;
28+
}
29+
};

0 commit comments

Comments
 (0)