From 8b37dba621dd9f5298cc50c8d76116fe3a1c4aff Mon Sep 17 00:00:00 2001 From: rain84 Date: Fri, 5 Jul 2024 22:18:13 +0300 Subject: [PATCH 01/13] feat: add ts solution to lc problem: No.1870 --- .../README.md | 31 +++++++++++++++++++ .../README_EN.md | 31 +++++++++++++++++++ .../Solution.ts | 26 ++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.ts diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md index 0d6ddf8f60d6e..3db1b51a9ad78 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md @@ -310,6 +310,37 @@ function arriveOnTime(dist, speed, hour) { } ``` +#### TypeScript + +```ts +function minSpeedOnTime(dist: number[], hour: number): number { + if (dist.length > Math.ceil(hour)) return -1; + + const check = (speed: number) => { + const n = dist.length; + let time = 0; + + for (let i = 0; i < n; i++) { + const t = dist[i] / speed; + time += i === n - 1 ? t : Math.ceil(t); + } + + return hour >= time; + }; + + const max = 10 ** 7; + let [l, r] = [1, max]; + + while (l <= r) { + const i = (l + r) >> 1; + if (check(i)) r = i - 1; + else l = i + 1; + } + + return l <= max ? l : -1; +} +``` + diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md index 04815774eaef8..5950b92c7274e 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md @@ -255,6 +255,37 @@ function arriveOnTime(dist, speed, hour) { } ``` +#### TypeScript + +```ts +function minSpeedOnTime(dist: number[], hour: number): number { + if (dist.length > Math.ceil(hour)) return -1; + + const check = (speed: number) => { + const n = dist.length; + let time = 0; + + for (let i = 0; i < n; i++) { + const t = dist[i] / speed; + time += i === n - 1 ? t : Math.ceil(t); + } + + return hour >= time; + }; + + const max = 10 ** 7; + let [l, r] = [1, max]; + + while (l <= r) { + const i = (l + r) >> 1; + if (check(i)) r = i - 1; + else l = i + 1; + } + + return l <= max ? l : -1; +} +``` + diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.ts b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.ts new file mode 100644 index 0000000000000..e4250b3f11d20 --- /dev/null +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.ts @@ -0,0 +1,26 @@ +function minSpeedOnTime(dist: number[], hour: number): number { + if (dist.length > Math.ceil(hour)) return -1; + + const check = (speed: number) => { + const n = dist.length; + let time = 0; + + for (let i = 0; i < n; i++) { + const t = dist[i] / speed; + time += i === n - 1 ? t : Math.ceil(t); + } + + return hour >= time; + }; + + const max = 10 ** 7; + let [l, r] = [1, max]; + + while (l <= r) { + const i = (l + r) >> 1; + if (check(i)) r = i - 1; + else l = i + 1; + } + + return l <= max ? l : -1; +} From 61bf4e340d02be1539bfcde0f7d28a816912b2f5 Mon Sep 17 00:00:00 2001 From: rain84 Date: Fri, 5 Jul 2024 22:32:54 +0300 Subject: [PATCH 02/13] feat: update js solution to lc problem: No.1870 --- .../1800-1899/1870.Minimum Speed to Arrive on Time/README.md | 2 +- .../1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md | 2 +- .../1800-1899/1870.Minimum Speed to Arrive on Time/Solution.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md index 3db1b51a9ad78..0383a581e43b0 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md @@ -300,7 +300,7 @@ function arriveOnTime(dist, speed, hour) { let res = 0.0; let n = dist.length; for (let i = 0; i < n; i++) { - let cost = parseFloat(dist[i]) / speed; + let cost = dist[i] / speed; if (i != n - 1) { cost = Math.ceil(cost); } diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md index 5950b92c7274e..73e226f944111 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md @@ -245,7 +245,7 @@ function arriveOnTime(dist, speed, hour) { let res = 0.0; let n = dist.length; for (let i = 0; i < n; i++) { - let cost = parseFloat(dist[i]) / speed; + let cost = dist[i] / speed; if (i != n - 1) { cost = Math.ceil(cost); } diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.js b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.js index 80448463da1f6..def4fedf05526 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.js +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.js @@ -22,7 +22,7 @@ function arriveOnTime(dist, speed, hour) { let res = 0.0; let n = dist.length; for (let i = 0; i < n; i++) { - let cost = parseFloat(dist[i]) / speed; + let cost = dist[i] / speed; if (i != n - 1) { cost = Math.ceil(cost); } From 5bb27b22ab2fa707208c3c4a7b83e5e722f97caa Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:15:45 +0800 Subject: [PATCH 03/13] Update README.md --- .../README.md | 305 ++++++++---------- 1 file changed, 137 insertions(+), 168 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md index 0383a581e43b0..1a1399dde18fe 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md @@ -83,60 +83,15 @@ tags: ### 方法一:二分查找 -二分枚举速度值,找到满足条件的最小速度。 +我们注意到,如果一个速度值 $v$ 能够使得我们在规定时间内到达,那么对于任意 $v' > v$,我们也一定能在规定时间内到达。这存在着单调性,因此我们可以使用二分查找,找到最小的满足条件的速度值。 -时间复杂度 $O(n\times \log m)$,其中 $n$ 和 $m$ 分别为数组 `dist` 和最大速度值。 +我们可以二分枚举速度值,首先定义二分的左右边界为 $l = 1$, $r = 10^7 + 1$,然后我们每次取中间值 $\text{mid} = \frac{l + r}{2}$,判断是否满足条件。如果满足条件,我们将右边界移动到 $\text{mid}$,否则将左边界移动到 $\text{mid} + 1$。 -以下是二分查找的两个通用模板: +问题转化为判断一个速度值 $v$ 是否能够在规定时间内到达。我们可以遍历每一趟列车,计算每一趟列车的运行时间 $t = \frac{d}{v}$,如果是最后一趟列车,我们直接加上 $t$,否则我们向上取整加上 $t$。最后判断总时间是否小于等于规定时间,如果是则说明满足条件。 -模板 1: +二分结束后,如果左边界超过了 $10^7$,说明无法在规定时间内到达,返回 $-1$,否则返回左边界。 -```java -boolean check(int x) { -} - -int search(int left, int right) { - while (left < right) { - int mid = (left + right) >> 1; - if (check(mid)) { - right = mid; - } else { - left = mid + 1; - } - } - return left; -} -``` - -模板 2: - -```java -boolean check(int x) { -} - -int search(int left, int right) { - while (left < right) { - int mid = (left + right + 1) >> 1; - if (check(mid)) { - left = mid; - } else { - right = mid - 1; - } - } - return left; -} -``` - -做二分题目时,可以按照以下套路: - -1. 写出循环条件 $left < right$; -1. 循环体内,不妨先写 $mid = \lfloor \frac{left + right}{2} \rfloor$; -1. 根据具体题目,实现 $check()$ 函数(有时很简单的逻辑,可以不定义 $check$),想一下究竟要用 $right = mid$(模板 $1$) 还是 $left = mid$(模板 $2$); -     - 如果 $right = mid$,那么写出 else 语句 $left = mid + 1$,并且不需要更改 mid 的计算,即保持 $mid = \lfloor \frac{left + right}{2} \rfloor$; -     - 如果 $left = mid$,那么写出 else 语句 $right = mid - 1$,并且在 $mid$ 计算时补充 +1,即 $mid = \lfloor \frac{left + right + 1}{2} \rfloor$; -1. 循环结束时,$left$ 与 $right$ 相等。 - -注意,这两个模板的优点是始终保持答案位于二分区间内,二分结束条件对应的值恰好在答案所处的位置。 对于可能无解的情况,只要判断二分结束后的 $left$ 或者 $right$ 是否满足题意即可。 +时间复杂度 $O(n \times \log M)$,其中 $n$ 和 $M$ 分别为列车数量和速度的上界。空间复杂度 $O(1)$。 @@ -145,12 +100,15 @@ int search(int left, int right) { ```python class Solution: def minSpeedOnTime(self, dist: List[int], hour: float) -> int: - def check(speed): - res = 0 + def check(v: int) -> bool: + s = 0 for i, d in enumerate(dist): - res += (d / speed) if i == len(dist) - 1 else math.ceil(d / speed) - return res <= hour + t = d / v + s += t if i == len(dist) - 1 else ceil(t) + return s <= hour + if len(dist) > ceil(hour): + return -1 r = 10**7 + 1 ans = bisect_left(range(1, r), True, key=check) + 1 return -1 if ans == r else ans @@ -161,25 +119,30 @@ class Solution: ```java class Solution { public int minSpeedOnTime(int[] dist, double hour) { - int left = 1, right = (int) 1e7; - while (left < right) { - int mid = (left + right) >> 1; + if (dist.length > Math.ceil(hour)) { + return -1; + } + final int m = (int) 1e7; + int l = 1, r = m + 1; + while (l < r) { + int mid = (l + r) >> 1; if (check(dist, mid, hour)) { - right = mid; + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return check(dist, left, hour) ? left : -1; + return l > m ? -1 : l; } - private boolean check(int[] dist, int speed, double hour) { - double res = 0; - for (int i = 0; i < dist.length; ++i) { - double cost = dist[i] * 1.0 / speed; - res += (i == dist.length - 1 ? cost : Math.ceil(cost)); + private boolean check(int[] dist, int v, double hour) { + double s = 0; + int n = dist.length; + for (int i = 0; i < n; ++i) { + double t = dist[i] * 1.0 / v; + s += i == n - 1 ? t : Math.ceil(t); } - return res <= hour; + return s <= hour; } } ``` @@ -190,25 +153,29 @@ class Solution { class Solution { public: int minSpeedOnTime(vector& dist, double hour) { - int left = 1, right = 1e7; - while (left < right) { - int mid = (left + right) >> 1; - if (check(dist, mid, hour)) { - right = mid; + if (dist.size() > ceil(hour)) { + return -1; + } + const int m = 1e7; + int l = 1, r = m + 1; + int n = dist.size(); + auto check = [&](int v) { + double s = 0; + for (int i = 0; i < n; ++i) { + double t = dist[i] * 1.0 / v; + s += i == n - 1 ? t : ceil(t); + } + return s <= hour; + }; + while (l < r) { + int mid = (l + r) >> 1; + if (check(mid)) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return check(dist, left, hour) ? left : -1; - } - - bool check(vector& dist, int speed, double hour) { - double res = 0; - for (int i = 0; i < dist.size(); ++i) { - double cost = dist[i] * 1.0 / speed; - res += (i == dist.size() - 1 ? cost : ceil(cost)); - } - return res <= hour; + return l > m ? -1 : l; } }; ``` @@ -217,21 +184,58 @@ public: ```go func minSpeedOnTime(dist []int, hour float64) int { + if float64(len(dist)) > math.Ceil(hour) { + return -1 + } + const m int = 1e7 n := len(dist) - const mx int = 1e7 - x := sort.Search(mx, func(s int) bool { - s++ - var cost float64 - for _, v := range dist[:n-1] { - cost += math.Ceil(float64(v) / float64(s)) + ans := sort.Search(m+1, func(v int) bool { + v++ + s := 0.0 + for i, d := range dist { + t := float64(d) / float64(v) + if i == n-1 { + s += t + } else { + s += math.Ceil(t) + } } - cost += float64(dist[n-1]) / float64(s) - return cost <= hour - }) - if x == mx { + return s <= hour + }) + 1 + if ans > m { return -1 } - return x + 1 + return ans +} +``` + +#### TypeScript + +```ts +function minSpeedOnTime(dist: number[], hour: number): number { + if (dist.length > Math.ceil(hour)) { + return -1; + } + const n = dist.length; + const m = 10 ** 7; + const check = (v: number): boolean => { + let s = 0; + for (let i = 0; i < n; ++i) { + const t = dist[i] / v; + s += i === n - 1 ? t : Math.ceil(t); + } + return s <= hour; + }; + let [l, r] = [1, m + 1]; + while (l < r) { + const mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } + } + return l > m ? -1 : l; } ``` @@ -240,35 +244,33 @@ func minSpeedOnTime(dist []int, hour float64) int { ```rust impl Solution { pub fn min_speed_on_time(dist: Vec, hour: f64) -> i32 { + if dist.len() as f64 > hour.ceil() { + return -1; + } + const M: i32 = 10_000_000; + let (mut l, mut r) = (1, M + 1); let n = dist.len(); - - let check = |speed| { - let mut cur = 0.0; - for (i, &d) in dist.iter().enumerate() { - if i == n - 1 { - cur += (d as f64) / (speed as f64); - } else { - cur += ((d as f64) / (speed as f64)).ceil(); - } + let check = |v: i32| -> bool { + let mut s = 0.0; + for i in 0..n { + let t = dist[i] as f64 / v as f64; + s += if i == n - 1 { t } else { t.ceil() }; } - cur <= hour + s <= hour }; - - let mut left = 1; - let mut right = 1e7 as i32; - while left < right { - let mid = left + (right - left) / 2; - if !check(mid) { - left = mid + 1; + while l < r { + let mid = (l + r) / 2; + if check(mid) { + r = mid; } else { - right = mid; + l = mid + 1; } } - - if check(left) { - return left; + if l > M { + -1 + } else { + l } - -1 } } ``` @@ -282,63 +284,30 @@ impl Solution { * @return {number} */ var minSpeedOnTime = function (dist, hour) { - if (dist.length > Math.ceil(hour)) return -1; - let left = 1, - right = 10 ** 7; - while (left < right) { - let mid = (left + right) >> 1; - if (arriveOnTime(dist, mid, hour)) { - right = mid; - } else { - left = mid + 1; - } - } - return left; -}; - -function arriveOnTime(dist, speed, hour) { - let res = 0.0; - let n = dist.length; - for (let i = 0; i < n; i++) { - let cost = dist[i] / speed; - if (i != n - 1) { - cost = Math.ceil(cost); - } - res += cost; + if (dist.length > Math.ceil(hour)) { + return -1; } - return res <= hour; -} -``` - -#### TypeScript - -```ts -function minSpeedOnTime(dist: number[], hour: number): number { - if (dist.length > Math.ceil(hour)) return -1; - - const check = (speed: number) => { - const n = dist.length; - let time = 0; - - for (let i = 0; i < n; i++) { - const t = dist[i] / speed; - time += i === n - 1 ? t : Math.ceil(t); + const n = dist.length; + const m = 10 ** 7; + const check = v => { + let s = 0; + for (let i = 0; i < n; ++i) { + const t = dist[i] / v; + s += i === n - 1 ? t : Math.ceil(t); } - - return hour >= time; + return s <= hour; }; - - const max = 10 ** 7; - let [l, r] = [1, max]; - - while (l <= r) { - const i = (l + r) >> 1; - if (check(i)) r = i - 1; - else l = i + 1; + let [l, r] = [1, m + 1]; + while (l < r) { + const mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } } - - return l <= max ? l : -1; -} + return l > m ? -1 : l; +}; ``` From c7bbaf843d2dd062da2beb712ce64b7f2c3405c4 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:15:57 +0800 Subject: [PATCH 04/13] Update README_EN.md --- .../README_EN.md | 262 ++++++++++-------- 1 file changed, 143 insertions(+), 119 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md index 73e226f944111..4a18a1ebe8a5a 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md @@ -81,7 +81,17 @@ tags: -### Solution 1 +### Solution 1: Binary Search + +We notice that if a speed value $v$ allows us to arrive within the stipulated time, then for any $v' > v$, we can also definitely arrive within the stipulated time. This exhibits monotonicity, hence we can use binary search to find the smallest speed value that meets the condition. + +We can enumerate the speed value using binary search. First, we define the left and right boundaries of the binary search as $l = 1$, $r = 10^7 + 1$, and then we take the middle value $\text{mid} = \frac{l + r}{2}$ each time to check if it meets the condition. If it does, we move the right boundary to $\text{mid}$; otherwise, we move the left boundary to $\text{mid} + 1$. + +The problem is transformed into determining whether a speed value $v$ can allow us to arrive within the stipulated time. We can traverse each train trip, calculate the running time of each trip $t = \frac{d}{v}$, if it is the last trip, we directly add $t$; otherwise, we round up and add $t$. Finally, we check if the total time is less than or equal to the stipulated time, if so, it means the condition is met. + +After the binary search ends, if the left boundary exceeds $10^7$, it means we cannot arrive within the stipulated time, and we return $-1$; otherwise, we return the left boundary. + +The time complexity is $O(n \times \log M)$, where $n$ and $M$ are the number of train trips and the upper bound of the speed, respectively. The space complexity is $O(1)$. @@ -90,12 +100,15 @@ tags: ```python class Solution: def minSpeedOnTime(self, dist: List[int], hour: float) -> int: - def check(speed): - res = 0 + def check(v: int) -> bool: + s = 0 for i, d in enumerate(dist): - res += (d / speed) if i == len(dist) - 1 else math.ceil(d / speed) - return res <= hour + t = d / v + s += t if i == len(dist) - 1 else ceil(t) + return s <= hour + if len(dist) > ceil(hour): + return -1 r = 10**7 + 1 ans = bisect_left(range(1, r), True, key=check) + 1 return -1 if ans == r else ans @@ -106,25 +119,30 @@ class Solution: ```java class Solution { public int minSpeedOnTime(int[] dist, double hour) { - int left = 1, right = (int) 1e7; - while (left < right) { - int mid = (left + right) >> 1; + if (dist.length > Math.ceil(hour)) { + return -1; + } + final int m = (int) 1e7; + int l = 1, r = m + 1; + while (l < r) { + int mid = (l + r) >> 1; if (check(dist, mid, hour)) { - right = mid; + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return check(dist, left, hour) ? left : -1; + return l > m ? -1 : l; } - private boolean check(int[] dist, int speed, double hour) { - double res = 0; - for (int i = 0; i < dist.length; ++i) { - double cost = dist[i] * 1.0 / speed; - res += (i == dist.length - 1 ? cost : Math.ceil(cost)); + private boolean check(int[] dist, int v, double hour) { + double s = 0; + int n = dist.length; + for (int i = 0; i < n; ++i) { + double t = dist[i] * 1.0 / v; + s += i == n - 1 ? t : Math.ceil(t); } - return res <= hour; + return s <= hour; } } ``` @@ -135,25 +153,29 @@ class Solution { class Solution { public: int minSpeedOnTime(vector& dist, double hour) { - int left = 1, right = 1e7; - while (left < right) { - int mid = (left + right) >> 1; - if (check(dist, mid, hour)) { - right = mid; + if (dist.size() > ceil(hour)) { + return -1; + } + const int m = 1e7; + int l = 1, r = m + 1; + int n = dist.size(); + auto check = [&](int v) { + double s = 0; + for (int i = 0; i < n; ++i) { + double t = dist[i] * 1.0 / v; + s += i == n - 1 ? t : ceil(t); + } + return s <= hour; + }; + while (l < r) { + int mid = (l + r) >> 1; + if (check(mid)) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return check(dist, left, hour) ? left : -1; - } - - bool check(vector& dist, int speed, double hour) { - double res = 0; - for (int i = 0; i < dist.size(); ++i) { - double cost = dist[i] * 1.0 / speed; - res += (i == dist.size() - 1 ? cost : ceil(cost)); - } - return res <= hour; + return l > m ? -1 : l; } }; ``` @@ -162,21 +184,58 @@ public: ```go func minSpeedOnTime(dist []int, hour float64) int { + if float64(len(dist)) > math.Ceil(hour) { + return -1 + } + const m int = 1e7 n := len(dist) - const mx int = 1e7 - x := sort.Search(mx, func(s int) bool { - s++ - var cost float64 - for _, v := range dist[:n-1] { - cost += math.Ceil(float64(v) / float64(s)) + ans := sort.Search(m+1, func(v int) bool { + v++ + s := 0.0 + for i, d := range dist { + t := float64(d) / float64(v) + if i == n-1 { + s += t + } else { + s += math.Ceil(t) + } } - cost += float64(dist[n-1]) / float64(s) - return cost <= hour - }) - if x == mx { + return s <= hour + }) + 1 + if ans > m { return -1 } - return x + 1 + return ans +} +``` + +#### TypeScript + +```ts +function minSpeedOnTime(dist: number[], hour: number): number { + if (dist.length > Math.ceil(hour)) { + return -1; + } + const n = dist.length; + const m = 10 ** 7; + const check = (v: number): boolean => { + let s = 0; + for (let i = 0; i < n; ++i) { + const t = dist[i] / v; + s += i === n - 1 ? t : Math.ceil(t); + } + return s <= hour; + }; + let [l, r] = [1, m + 1]; + while (l < r) { + const mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } + } + return l > m ? -1 : l; } ``` @@ -185,35 +244,33 @@ func minSpeedOnTime(dist []int, hour float64) int { ```rust impl Solution { pub fn min_speed_on_time(dist: Vec, hour: f64) -> i32 { + if dist.len() as f64 > hour.ceil() { + return -1; + } + const M: i32 = 10_000_000; + let (mut l, mut r) = (1, M + 1); let n = dist.len(); - - let check = |speed| { - let mut cur = 0.0; - for (i, &d) in dist.iter().enumerate() { - if i == n - 1 { - cur += (d as f64) / (speed as f64); - } else { - cur += ((d as f64) / (speed as f64)).ceil(); - } + let check = |v: i32| -> bool { + let mut s = 0.0; + for i in 0..n { + let t = dist[i] as f64 / v as f64; + s += if i == n - 1 { t } else { t.ceil() }; } - cur <= hour + s <= hour }; - - let mut left = 1; - let mut right = 1e7 as i32; - while left < right { - let mid = left + (right - left) / 2; - if !check(mid) { - left = mid + 1; + while l < r { + let mid = (l + r) / 2; + if check(mid) { + r = mid; } else { - right = mid; + l = mid + 1; } } - - if check(left) { - return left; + if l > M { + -1 + } else { + l } - -1 } } ``` @@ -227,63 +284,30 @@ impl Solution { * @return {number} */ var minSpeedOnTime = function (dist, hour) { - if (dist.length > Math.ceil(hour)) return -1; - let left = 1, - right = 10 ** 7; - while (left < right) { - let mid = (left + right) >> 1; - if (arriveOnTime(dist, mid, hour)) { - right = mid; - } else { - left = mid + 1; - } + if (dist.length > Math.ceil(hour)) { + return -1; } - return left; -}; - -function arriveOnTime(dist, speed, hour) { - let res = 0.0; - let n = dist.length; - for (let i = 0; i < n; i++) { - let cost = dist[i] / speed; - if (i != n - 1) { - cost = Math.ceil(cost); - } - res += cost; - } - return res <= hour; -} -``` - -#### TypeScript - -```ts -function minSpeedOnTime(dist: number[], hour: number): number { - if (dist.length > Math.ceil(hour)) return -1; - - const check = (speed: number) => { - const n = dist.length; - let time = 0; - - for (let i = 0; i < n; i++) { - const t = dist[i] / speed; - time += i === n - 1 ? t : Math.ceil(t); + const n = dist.length; + const m = 10 ** 7; + const check = v => { + let s = 0; + for (let i = 0; i < n; ++i) { + const t = dist[i] / v; + s += i === n - 1 ? t : Math.ceil(t); } - - return hour >= time; + return s <= hour; }; - - const max = 10 ** 7; - let [l, r] = [1, max]; - - while (l <= r) { - const i = (l + r) >> 1; - if (check(i)) r = i - 1; - else l = i + 1; + let [l, r] = [1, m + 1]; + while (l < r) { + const mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } } - - return l <= max ? l : -1; -} + return l > m ? -1 : l; +}; ``` From 5e248e51a8ccb5bc0e4e7765cfcad15eeffe0952 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:16:11 +0800 Subject: [PATCH 05/13] Update Solution.js --- .../Solution.js | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.js b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.js index def4fedf05526..377a8419bbb8c 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.js +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.js @@ -4,29 +4,27 @@ * @return {number} */ var minSpeedOnTime = function (dist, hour) { - if (dist.length > Math.ceil(hour)) return -1; - let left = 1, - right = 10 ** 7; - while (left < right) { - let mid = (left + right) >> 1; - if (arriveOnTime(dist, mid, hour)) { - right = mid; + if (dist.length > Math.ceil(hour)) { + return -1; + } + const n = dist.length; + const m = 10 ** 7; + const check = v => { + let s = 0; + for (let i = 0; i < n; ++i) { + const t = dist[i] / v; + s += i === n - 1 ? t : Math.ceil(t); + } + return s <= hour; + }; + let [l, r] = [1, m + 1]; + while (l < r) { + const mid = (l + r) >> 1; + if (check(mid)) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return left; + return l > m ? -1 : l; }; - -function arriveOnTime(dist, speed, hour) { - let res = 0.0; - let n = dist.length; - for (let i = 0; i < n; i++) { - let cost = dist[i] / speed; - if (i != n - 1) { - cost = Math.ceil(cost); - } - res += cost; - } - return res <= hour; -} From dd6291d8ea7c10317354c5a67cb3bb0305cb86e7 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:16:22 +0800 Subject: [PATCH 06/13] Update Solution.ts --- .../Solution.ts | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.ts b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.ts index e4250b3f11d20..03752f4c030e5 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.ts +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.ts @@ -1,26 +1,25 @@ function minSpeedOnTime(dist: number[], hour: number): number { - if (dist.length > Math.ceil(hour)) return -1; - - const check = (speed: number) => { - const n = dist.length; - let time = 0; - - for (let i = 0; i < n; i++) { - const t = dist[i] / speed; - time += i === n - 1 ? t : Math.ceil(t); + if (dist.length > Math.ceil(hour)) { + return -1; + } + const n = dist.length; + const m = 10 ** 7; + const check = (v: number): boolean => { + let s = 0; + for (let i = 0; i < n; ++i) { + const t = dist[i] / v; + s += i === n - 1 ? t : Math.ceil(t); } - - return hour >= time; + return s <= hour; }; - - const max = 10 ** 7; - let [l, r] = [1, max]; - - while (l <= r) { - const i = (l + r) >> 1; - if (check(i)) r = i - 1; - else l = i + 1; + let [l, r] = [1, m + 1]; + while (l < r) { + const mid = (l + r) >> 1; + if (check(mid)) { + r = mid; + } else { + l = mid + 1; + } } - - return l <= max ? l : -1; + return l > m ? -1 : l; } From 62613e3264b108c29e554ea00c5de6baebbd6fe4 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:16:47 +0800 Subject: [PATCH 07/13] Update Solution.py --- .../1870.Minimum Speed to Arrive on Time/Solution.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.py b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.py index 3203eb12897e4..697eab7d6d9eb 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.py +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.py @@ -1,11 +1,14 @@ class Solution: def minSpeedOnTime(self, dist: List[int], hour: float) -> int: - def check(speed): - res = 0 + def check(v: int) -> bool: + s = 0 for i, d in enumerate(dist): - res += (d / speed) if i == len(dist) - 1 else math.ceil(d / speed) - return res <= hour + t = d / v + s += t if i == len(dist) - 1 else ceil(t) + return s <= hour + if len(dist) > ceil(hour): + return -1 r = 10**7 + 1 ans = bisect_left(range(1, r), True, key=check) + 1 return -1 if ans == r else ans From c2c9a4af0ca57645fc353ab8a6e74d822924c685 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:16:57 +0800 Subject: [PATCH 08/13] Update Solution.java --- .../Solution.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.java b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.java index 13073b0883c45..ca2f5160693c3 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.java +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.java @@ -1,23 +1,28 @@ class Solution { public int minSpeedOnTime(int[] dist, double hour) { - int left = 1, right = (int) 1e7; - while (left < right) { - int mid = (left + right) >> 1; + if (dist.length > Math.ceil(hour)) { + return -1; + } + final int m = (int) 1e7; + int l = 1, r = m + 1; + while (l < r) { + int mid = (l + r) >> 1; if (check(dist, mid, hour)) { - right = mid; + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return check(dist, left, hour) ? left : -1; + return l > m ? -1 : l; } - private boolean check(int[] dist, int speed, double hour) { - double res = 0; - for (int i = 0; i < dist.length; ++i) { - double cost = dist[i] * 1.0 / speed; - res += (i == dist.length - 1 ? cost : Math.ceil(cost)); + private boolean check(int[] dist, int v, double hour) { + double s = 0; + int n = dist.length; + for (int i = 0; i < n; ++i) { + double t = dist[i] * 1.0 / v; + s += i == n - 1 ? t : Math.ceil(t); } - return res <= hour; + return s <= hour; } -} \ No newline at end of file +} From fc96647ddd5f38c5d6b37af5cb75f5171697861d Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:17:08 +0800 Subject: [PATCH 09/13] Update Solution.cpp --- .../Solution.cpp | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.cpp b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.cpp index ec80ca0547251..0083993ce4955 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.cpp +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.cpp @@ -1,24 +1,28 @@ class Solution { public: int minSpeedOnTime(vector& dist, double hour) { - int left = 1, right = 1e7; - while (left < right) { - int mid = (left + right) >> 1; - if (check(dist, mid, hour)) { - right = mid; + if (dist.size() > ceil(hour)) { + return -1; + } + const int m = 1e7; + int l = 1, r = m + 1; + int n = dist.size(); + auto check = [&](int v) { + double s = 0; + for (int i = 0; i < n; ++i) { + double t = dist[i] * 1.0 / v; + s += i == n - 1 ? t : ceil(t); + } + return s <= hour; + }; + while (l < r) { + int mid = (l + r) >> 1; + if (check(mid)) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return check(dist, left, hour) ? left : -1; - } - - bool check(vector& dist, int speed, double hour) { - double res = 0; - for (int i = 0; i < dist.size(); ++i) { - double cost = dist[i] * 1.0 / speed; - res += (i == dist.size() - 1 ? cost : ceil(cost)); - } - return res <= hour; + return l > m ? -1 : l; } -}; \ No newline at end of file +}; From f33c9efbea0e0bedd74b32e24fe5001c6d026473 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:17:16 +0800 Subject: [PATCH 10/13] Update Solution.go --- .../Solution.go | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.go b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.go index d1c0d941cc2a2..9f1c04909d5b2 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.go +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.go @@ -1,17 +1,24 @@ func minSpeedOnTime(dist []int, hour float64) int { + if float64(len(dist)) > math.Ceil(hour) { + return -1 + } + const m int = 1e7 n := len(dist) - const mx int = 1e7 - x := sort.Search(mx, func(s int) bool { - s++ - var cost float64 - for _, v := range dist[:n-1] { - cost += math.Ceil(float64(v) / float64(s)) + ans := sort.Search(m+1, func(v int) bool { + v++ + s := 0.0 + for i, d := range dist { + t := float64(d) / float64(v) + if i == n-1 { + s += t + } else { + s += math.Ceil(t) + } } - cost += float64(dist[n-1]) / float64(s) - return cost <= hour - }) - if x == mx { + return s <= hour + }) + 1 + if ans > m { return -1 } - return x + 1 -} \ No newline at end of file + return ans +} From c0634c1874c2af73c1bb36aa7a79c439701ceb27 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:17:25 +0800 Subject: [PATCH 11/13] Update Solution.rs --- .../Solution.rs | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.rs b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.rs index 018def82d7bd1..0f5426eea5131 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.rs +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.rs @@ -1,33 +1,31 @@ impl Solution { pub fn min_speed_on_time(dist: Vec, hour: f64) -> i32 { + if dist.len() as f64 > hour.ceil() { + return -1; + } + const M: i32 = 10_000_000; + let (mut l, mut r) = (1, M + 1); let n = dist.len(); - - let check = |speed| { - let mut cur = 0.0; - for (i, &d) in dist.iter().enumerate() { - if i == n - 1 { - cur += (d as f64) / (speed as f64); - } else { - cur += ((d as f64) / (speed as f64)).ceil(); - } + let check = |v: i32| -> bool { + let mut s = 0.0; + for i in 0..n { + let t = dist[i] as f64 / v as f64; + s += if i == n - 1 { t } else { t.ceil() }; } - cur <= hour + s <= hour }; - - let mut left = 1; - let mut right = 1e7 as i32; - while left < right { - let mid = left + (right - left) / 2; - if !check(mid) { - left = mid + 1; + while l < r { + let mid = (l + r) / 2; + if check(mid) { + r = mid; } else { - right = mid; + l = mid + 1; } } - - if check(left) { - return left; + if l > M { + -1 + } else { + l } - -1 } } From 0bf283acfa3b759eed099df4f089fb11d8ee02eb Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:19:03 +0800 Subject: [PATCH 12/13] Update README.md --- .../1800-1899/1870.Minimum Speed to Arrive on Time/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md index 1a1399dde18fe..b429e2b9e0d9d 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md @@ -85,7 +85,9 @@ tags: 我们注意到,如果一个速度值 $v$ 能够使得我们在规定时间内到达,那么对于任意 $v' > v$,我们也一定能在规定时间内到达。这存在着单调性,因此我们可以使用二分查找,找到最小的满足条件的速度值。 -我们可以二分枚举速度值,首先定义二分的左右边界为 $l = 1$, $r = 10^7 + 1$,然后我们每次取中间值 $\text{mid} = \frac{l + r}{2}$,判断是否满足条件。如果满足条件,我们将右边界移动到 $\text{mid}$,否则将左边界移动到 $\text{mid} + 1$。 +在二分查找之前,我们需要先判断是否有可能在规定时间内到达。如果列车数量大于向上取整的规定时间,那么一定无法在规定时间内到达,直接返回 $-1$。 + +接下来,我们定义二分的左右边界为 $l = 1$, $r = 10^7 + 1$,然后我们每次取中间值 $\text{mid} = \frac{l + r}{2}$,判断是否满足条件。如果满足条件,我们将右边界移动到 $\text{mid}$,否则将左边界移动到 $\text{mid} + 1$。 问题转化为判断一个速度值 $v$ 是否能够在规定时间内到达。我们可以遍历每一趟列车,计算每一趟列车的运行时间 $t = \frac{d}{v}$,如果是最后一趟列车,我们直接加上 $t$,否则我们向上取整加上 $t$。最后判断总时间是否小于等于规定时间,如果是则说明满足条件。 From 4a106d9f9e0d412f5df53077dd164d7b6cb38095 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 6 Jul 2024 08:19:32 +0800 Subject: [PATCH 13/13] Update README_EN.md --- .../1870.Minimum Speed to Arrive on Time/README_EN.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md index 4a18a1ebe8a5a..48acea1aa2c99 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md @@ -85,7 +85,9 @@ tags: We notice that if a speed value $v$ allows us to arrive within the stipulated time, then for any $v' > v$, we can also definitely arrive within the stipulated time. This exhibits monotonicity, hence we can use binary search to find the smallest speed value that meets the condition. -We can enumerate the speed value using binary search. First, we define the left and right boundaries of the binary search as $l = 1$, $r = 10^7 + 1$, and then we take the middle value $\text{mid} = \frac{l + r}{2}$ each time to check if it meets the condition. If it does, we move the right boundary to $\text{mid}$; otherwise, we move the left boundary to $\text{mid} + 1$. +Before conducting the binary search, we need to first determine if it is possible to arrive within the stipulated time. If the number of trains is greater than the ceiling of the stipulated time, then it is definitely impossible to arrive within the stipulated time, and we should directly return $-1$. + +Next, we define the left and right boundaries for the binary search as $l = 1$, $r = 10^7 + 1$, and then we take the middle value $\text{mid} = \frac{l + r}{2}$ each time to check if it meets the condition. If it does, we move the right boundary to $\text{mid}$; otherwise, we move the left boundary to $\text{mid} + 1$. The problem is transformed into determining whether a speed value $v$ can allow us to arrive within the stipulated time. We can traverse each train trip, calculate the running time of each trip $t = \frac{d}{v}$, if it is the last trip, we directly add $t$; otherwise, we round up and add $t$. Finally, we check if the total time is less than or equal to the stipulated time, if so, it means the condition is met.