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 b47303f

Browse files
rain84yanglbme
andauthored
feat: update solutions to lc problem: No.1870 (doocs#3206)
Co-authored-by: Libin YANG <contact@yanglibin.info>
1 parent a491049 commit b47303f

File tree

9 files changed

+413
-314
lines changed

9 files changed

+413
-314
lines changed

‎solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md‎

Lines changed: 138 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -83,60 +83,17 @@ tags:
8383

8484
### 方法一:二分查找
8585

86-
二分枚举速度值,找到满足条件的最小速度
86+
我们注意到,如果一个速度值 $v$ 能够使得我们在规定时间内到达,那么对于任意 $v' > v,ドル我们也一定能在规定时间内到达。这存在着单调性,因此我们可以使用二分查找,找到最小的满足条件的速度值
8787

88-
时间复杂度 $O(n\times \log m),ドル其中 $n$ 和 $m$ 分别为数组 `dist` 和最大速度值
88+
在二分查找之前,我们需要先判断是否有可能在规定时间内到达。如果列车数量大于向上取整的规定时间,那么一定无法在规定时间内到达,直接返回 $-1$
8989

90-
以下是二分查找的两个通用模板:
90+
接下来,我们定义二分的左右边界为 $l = 1,ドル $r = 10^7 + 1,ドル然后我们每次取中间值 $\text{mid} = \frac{l + r}{2},ドル判断是否满足条件。如果满足条件,我们将右边界移动到 $\text{mid},ドル否则将左边界移动到 $\text{mid} + 1$。
9191

92-
模板 1:
92+
问题转化为判断一个速度值 $v$ 是否能够在规定时间内到达。我们可以遍历每一趟列车,计算每一趟列车的运行时间 $t = \frac{d}{v},ドル如果是最后一趟列车,我们直接加上 $t,ドル否则我们向上取整加上 $t$。最后判断总时间是否小于等于规定时间,如果是则说明满足条件。
9393

94-
```java
95-
boolean check(int x) {
96-
}
97-
98-
int search(int left, int right) {
99-
while (left < right) {
100-
int mid = (left + right) >> 1;
101-
if (check(mid)) {
102-
right = mid;
103-
} else {
104-
left = mid + 1;
105-
}
106-
}
107-
return left;
108-
}
109-
```
94+
二分结束后,如果左边界超过了 10ドル^7,ドル说明无法在规定时间内到达,返回 $-1,ドル否则返回左边界。
11095

111-
模板 2:
112-
113-
```java
114-
boolean check(int x) {
115-
}
116-
117-
int search(int left, int right) {
118-
while (left < right) {
119-
int mid = (left + right + 1) >> 1;
120-
if (check(mid)) {
121-
left = mid;
122-
} else {
123-
right = mid - 1;
124-
}
125-
}
126-
return left;
127-
}
128-
```
129-
130-
做二分题目时,可以按照以下套路:
131-
132-
1. 写出循环条件 $left < right$;
133-
1. 循环体内,不妨先写 $mid = \lfloor \frac{left + right}{2} \rfloor$;
134-
1. 根据具体题目,实现 $check()$ 函数(有时很简单的逻辑,可以不定义 $check$),想一下究竟要用 $right = mid$(模板 1ドル$) 还是 $left = mid$(模板 2ドル$);
135-
- 如果 $right = mid,ドル那么写出 else 语句 $left = mid + 1,ドル并且不需要更改 mid 的计算,即保持 $mid = \lfloor \frac{left + right}{2} \rfloor$;
136-
- 如果 $left = mid,ドル那么写出 else 语句 $right = mid - 1,ドル并且在 $mid$ 计算时补充 +1,即 $mid = \lfloor \frac{left + right + 1}{2} \rfloor$;
137-
1. 循环结束时,$left$ 与 $right$ 相等。
138-
139-
注意,这两个模板的优点是始终保持答案位于二分区间内,二分结束条件对应的值恰好在答案所处的位置。 对于可能无解的情况,只要判断二分结束后的 $left$ 或者 $right$ 是否满足题意即可。
96+
时间复杂度 $O(n \times \log M),ドル其中 $n$ 和 $M$ 分别为列车数量和速度的上界。空间复杂度 $O(1)$。
14097

14198
<!-- tabs:start -->
14299

@@ -145,12 +102,15 @@ int search(int left, int right) {
145102
```python
146103
class Solution:
147104
def minSpeedOnTime(self, dist: List[int], hour: float) -> int:
148-
def check(speed):
149-
res = 0
105+
def check(v: int) -> bool:
106+
s = 0
150107
for i, d in enumerate(dist):
151-
res += (d / speed) if i == len(dist) - 1 else math.ceil(d / speed)
152-
return res <= hour
108+
t = d / v
109+
s += t if i == len(dist) - 1 else ceil(t)
110+
return s <= hour
153111

112+
if len(dist) > ceil(hour):
113+
return -1
154114
r = 10**7 + 1
155115
ans = bisect_left(range(1, r), True, key=check) + 1
156116
return -1 if ans == r else ans
@@ -161,25 +121,30 @@ class Solution:
161121
```java
162122
class Solution {
163123
public int minSpeedOnTime(int[] dist, double hour) {
164-
int left = 1, right = (int) 1e7;
165-
while (left < right) {
166-
int mid = (left + right) >> 1;
124+
if (dist.length > Math.ceil(hour)) {
125+
return -1;
126+
}
127+
final int m = (int) 1e7;
128+
int l = 1, r = m + 1;
129+
while (l < r) {
130+
int mid = (l + r) >> 1;
167131
if (check(dist, mid, hour)) {
168-
right = mid;
132+
r = mid;
169133
} else {
170-
left = mid + 1;
134+
l = mid + 1;
171135
}
172136
}
173-
return check(dist, left, hour) ? left : -1;
137+
return l > m ? -1 : l;
174138
}
175139

176-
private boolean check(int[] dist, int speed, double hour) {
177-
double res = 0;
178-
for (int i = 0; i < dist.length; ++i) {
179-
double cost = dist[i] * 1.0 / speed;
180-
res += (i == dist.length - 1 ? cost : Math.ceil(cost));
140+
private boolean check(int[] dist, int v, double hour) {
141+
double s = 0;
142+
int n = dist.length;
143+
for (int i = 0; i < n; ++i) {
144+
double t = dist[i] * 1.0 / v;
145+
s += i == n - 1 ? t : Math.ceil(t);
181146
}
182-
return res <= hour;
147+
return s <= hour;
183148
}
184149
}
185150
```
@@ -190,25 +155,29 @@ class Solution {
190155
class Solution {
191156
public:
192157
int minSpeedOnTime(vector<int>& dist, double hour) {
193-
int left = 1, right = 1e7;
194-
while (left < right) {
195-
int mid = (left + right) >> 1;
196-
if (check(dist, mid, hour)) {
197-
right = mid;
158+
if (dist.size() > ceil(hour)) {
159+
return -1;
160+
}
161+
const int m = 1e7;
162+
int l = 1, r = m + 1;
163+
int n = dist.size();
164+
auto check = [&](int v) {
165+
double s = 0;
166+
for (int i = 0; i < n; ++i) {
167+
double t = dist[i] * 1.0 / v;
168+
s += i == n - 1 ? t : ceil(t);
169+
}
170+
return s <= hour;
171+
};
172+
while (l < r) {
173+
int mid = (l + r) >> 1;
174+
if (check(mid)) {
175+
r = mid;
198176
} else {
199-
left = mid + 1;
177+
l = mid + 1;
200178
}
201179
}
202-
return check(dist, left, hour) ? left : -1;
203-
}
204-
205-
bool check(vector<int>& dist, int speed, double hour) {
206-
double res = 0;
207-
for (int i = 0; i < dist.size(); ++i) {
208-
double cost = dist[i] * 1.0 / speed;
209-
res += (i == dist.size() - 1 ? cost : ceil(cost));
210-
}
211-
return res <= hour;
180+
return l > m ? -1 : l;
212181
}
213182
};
214183
```
@@ -217,21 +186,58 @@ public:
217186
218187
```go
219188
func minSpeedOnTime(dist []int, hour float64) int {
189+
if float64(len(dist)) > math.Ceil(hour) {
190+
return -1
191+
}
192+
const m int = 1e7
220193
n := len(dist)
221-
const mx int = 1e7
222-
x := sort.Search(mx, func(s int) bool {
223-
s++
224-
var cost float64
225-
for _, v := range dist[:n-1] {
226-
cost += math.Ceil(float64(v) / float64(s))
194+
ans := sort.Search(m+1, func(v int) bool {
195+
v++
196+
s := 0.0
197+
for i, d := range dist {
198+
t := float64(d) / float64(v)
199+
if i == n-1 {
200+
s += t
201+
} else {
202+
s += math.Ceil(t)
203+
}
227204
}
228-
cost += float64(dist[n-1]) / float64(s)
229-
return cost <= hour
230-
})
231-
if x == mx {
205+
return s <= hour
206+
}) + 1
207+
if ans > m {
232208
return -1
233209
}
234-
return x + 1
210+
return ans
211+
}
212+
```
213+
214+
#### TypeScript
215+
216+
```ts
217+
function minSpeedOnTime(dist: number[], hour: number): number {
218+
if (dist.length > Math.ceil(hour)) {
219+
return -1;
220+
}
221+
const n = dist.length;
222+
const m = 10 ** 7;
223+
const check = (v: number): boolean => {
224+
let s = 0;
225+
for (let i = 0; i < n; ++i) {
226+
const t = dist[i] / v;
227+
s += i === n - 1 ? t : Math.ceil(t);
228+
}
229+
return s <= hour;
230+
};
231+
let [l, r] = [1, m + 1];
232+
while (l < r) {
233+
const mid = (l + r) >> 1;
234+
if (check(mid)) {
235+
r = mid;
236+
} else {
237+
l = mid + 1;
238+
}
239+
}
240+
return l > m ? -1 : l;
235241
}
236242
```
237243

@@ -240,35 +246,33 @@ func minSpeedOnTime(dist []int, hour float64) int {
240246
```rust
241247
impl Solution {
242248
pub fn min_speed_on_time(dist: Vec<i32>, hour: f64) -> i32 {
249+
if dist.len() as f64 > hour.ceil() {
250+
return -1;
251+
}
252+
const M: i32 = 10_000_000;
253+
let (mut l, mut r) = (1, M + 1);
243254
let n = dist.len();
244-
245-
let check = |speed| {
246-
let mut cur = 0.0;
247-
for (i, &d) in dist.iter().enumerate() {
248-
if i == n - 1 {
249-
cur += (d as f64) / (speed as f64);
250-
} else {
251-
cur += ((d as f64) / (speed as f64)).ceil();
252-
}
255+
let check = |v: i32| -> bool {
256+
let mut s = 0.0;
257+
for i in 0..n {
258+
let t = dist[i] as f64 / v as f64;
259+
s += if i == n - 1 { t } else { t.ceil() };
253260
}
254-
cur <= hour
261+
s <= hour
255262
};
256-
257-
let mut left = 1;
258-
let mut right = 1e7 as i32;
259-
while left < right {
260-
let mid = left + (right - left) / 2;
261-
if !check(mid) {
262-
left = mid + 1;
263+
while l < r {
264+
let mid = (l + r) / 2;
265+
if check(mid) {
266+
r = mid;
263267
} else {
264-
right = mid;
268+
l = mid+1;
265269
}
266270
}
267-
268-
if check(left) {
269-
return left;
271+
if l > M {
272+
-1
273+
} else {
274+
l
270275
}
271-
-1
272276
}
273277
}
274278
```
@@ -282,32 +286,30 @@ impl Solution {
282286
* @return {number}
283287
*/
284288
var minSpeedOnTime = function (dist, hour) {
285-
if (dist.length > Math.ceil(hour)) return -1;
286-
let left = 1,
287-
right = 10 ** 7;
288-
while (left < right) {
289-
let mid = (left + right) >> 1;
290-
if (arriveOnTime(dist, mid, hour)) {
291-
right = mid;
289+
if (dist.length > Math.ceil(hour)) {
290+
return -1;
291+
}
292+
const n = dist.length;
293+
const m = 10 ** 7;
294+
const check = v => {
295+
let s = 0;
296+
for (let i = 0; i < n; ++i) {
297+
const t = dist[i] / v;
298+
s += i === n - 1 ? t : Math.ceil(t);
299+
}
300+
return s <= hour;
301+
};
302+
let [l, r] = [1, m + 1];
303+
while (l < r) {
304+
const mid = (l + r) >> 1;
305+
if (check(mid)) {
306+
r = mid;
292307
} else {
293-
left = mid + 1;
308+
l = mid + 1;
294309
}
295310
}
296-
return left;
311+
return l > m ?-1: l;
297312
};
298-
299-
function arriveOnTime(dist, speed, hour) {
300-
let res = 0.0;
301-
let n = dist.length;
302-
for (let i = 0; i < n; i++) {
303-
let cost = parseFloat(dist[i]) / speed;
304-
if (i != n - 1) {
305-
cost = Math.ceil(cost);
306-
}
307-
res += cost;
308-
}
309-
return res <= hour;
310-
}
311313
```
312314

313315
<!-- tabs:end -->

0 commit comments

Comments
(0)

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