diff --git a/solution/0900-0999/0942.DI String Match/README.md b/solution/0900-0999/0942.DI String Match/README.md index e0cc78978275a..6766f0052aab8 100644 --- a/solution/0900-0999/0942.DI String Match/README.md +++ b/solution/0900-0999/0942.DI String Match/README.md @@ -65,7 +65,13 @@ tags: -### 方法一 +### 方法一:贪心 + +我们可以使用两个指针 `low` 和 `high` 分别表示当前的最小值和最大值,然后遍历字符串 `s`,如果当前字符是 `I`,那么我们就将 `low` 加入到结果数组中,并且 `low` 自增 1;如果当前字符是 `D`,那么我们就将 `high` 加入到结果数组中,并且 `high` 自减 1。 + +最后,我们将 `low` 加入到结果数组中,返回结果数组即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 `s` 的长度。 @@ -74,11 +80,10 @@ tags: ```python class Solution: def diStringMatch(self, s: str) -> List[int]: - n = len(s) - low, high = 0, n + low, high = 0, len(s) ans = [] - for i in range(n): - if s[i] == 'I': + for c in s: + if c == "I": ans.append(low) low += 1 else: @@ -134,12 +139,10 @@ public: #### Go ```go -func diStringMatch(s string) []int { - n := len(s) - low, high := 0, n - var ans []int - for i := 0; i < n; i++ { - if s[i] == 'I' { +func diStringMatch(s string) (ans []int) { + low, high := 0, len(s) + for _, c := range s { + if c == 'I' { ans = append(ans, low) low++ } else { @@ -148,7 +151,7 @@ func diStringMatch(s string) []int { } } ans = append(ans, low) - return ans + return } ``` @@ -156,19 +159,17 @@ func diStringMatch(s string) []int { ```ts function diStringMatch(s: string): number[] { - const n = s.length; - const res = new Array(n + 1); - let low = 0; - let high = n; - for (let i = 0; i < n; i++) { - if (s[i] === 'I') { - res[i] = low++; + const ans: number[] = []; + let [low, high] = [0, s.length]; + for (const c of s) { + if (c === 'I') { + ans.push(low++); } else { - res[i] = high--; + ans.push(high--); } } - res[n] = low; - return res; + ans.push(low); + return ans; } ``` @@ -177,21 +178,22 @@ function diStringMatch(s: string): number[] { ```rust impl Solution { pub fn di_string_match(s: String) -> Vec { - let s = s.as_bytes(); - let n = s.len(); - let mut res = Vec::with_capacity(n + 1); - let (mut low, mut high) = (-1, (n + 1) as i32); - for i in 0..n { - res.push(if s[i] == b'I' { + let mut low = 0; + let mut high = s.len() as i32; + let mut ans = Vec::with_capacity(s.len() + 1); + + for c in s.chars() { + if c == 'I' { + ans.push(low); low += 1; - low } else { + ans.push(high); high -= 1; - high - }); + } } - res.push(low + 1); - res + + ans.push(low); + ans } } ``` diff --git a/solution/0900-0999/0942.DI String Match/README_EN.md b/solution/0900-0999/0942.DI String Match/README_EN.md index 53c6fd96b3ee6..3bccf78c45cde 100644 --- a/solution/0900-0999/0942.DI String Match/README_EN.md +++ b/solution/0900-0999/0942.DI String Match/README_EN.md @@ -53,7 +53,13 @@ tags: -### Solution 1 +### Solution 1: Greedy Algorithm + +We can use two pointers `low` and `high` to represent the current minimum and maximum values, respectively. Then, we traverse the string `s`. If the current character is `I`, we add `low` to the result array, and increment `low` by 1; if the current character is `D`, we add `high` to the result array, and decrement `high` by 1. + +Finally, we add `low` to the result array and return the result array. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the string `s`. @@ -62,11 +68,10 @@ tags: ```python class Solution: def diStringMatch(self, s: str) -> List[int]: - n = len(s) - low, high = 0, n + low, high = 0, len(s) ans = [] - for i in range(n): - if s[i] == 'I': + for c in s: + if c == "I": ans.append(low) low += 1 else: @@ -122,12 +127,10 @@ public: #### Go ```go -func diStringMatch(s string) []int { - n := len(s) - low, high := 0, n - var ans []int - for i := 0; i < n; i++ { - if s[i] == 'I' { +func diStringMatch(s string) (ans []int) { + low, high := 0, len(s) + for _, c := range s { + if c == 'I' { ans = append(ans, low) low++ } else { @@ -136,7 +139,7 @@ func diStringMatch(s string) []int { } } ans = append(ans, low) - return ans + return } ``` @@ -144,19 +147,17 @@ func diStringMatch(s string) []int { ```ts function diStringMatch(s: string): number[] { - const n = s.length; - const res = new Array(n + 1); - let low = 0; - let high = n; - for (let i = 0; i < n; i++) { - if (s[i] === 'I') { - res[i] = low++; + const ans: number[] = []; + let [low, high] = [0, s.length]; + for (const c of s) { + if (c === 'I') { + ans.push(low++); } else { - res[i] = high--; + ans.push(high--); } } - res[n] = low; - return res; + ans.push(low); + return ans; } ``` @@ -165,21 +166,22 @@ function diStringMatch(s: string): number[] { ```rust impl Solution { pub fn di_string_match(s: String) -> Vec { - let s = s.as_bytes(); - let n = s.len(); - let mut res = Vec::with_capacity(n + 1); - let (mut low, mut high) = (-1, (n + 1) as i32); - for i in 0..n { - res.push(if s[i] == b'I' { + let mut low = 0; + let mut high = s.len() as i32; + let mut ans = Vec::with_capacity(s.len() + 1); + + for c in s.chars() { + if c == 'I' { + ans.push(low); low += 1; - low } else { + ans.push(high); high -= 1; - high - }); + } } - res.push(low + 1); - res + + ans.push(low); + ans } } ``` diff --git a/solution/0900-0999/0942.DI String Match/Solution.go b/solution/0900-0999/0942.DI String Match/Solution.go index 5a0f67bb74c93..d2cb36c905c81 100644 --- a/solution/0900-0999/0942.DI String Match/Solution.go +++ b/solution/0900-0999/0942.DI String Match/Solution.go @@ -1,9 +1,7 @@ -func diStringMatch(s string) []int { - n := len(s) - low, high := 0, n - var ans []int - for i := 0; i < n; i++ { - if s[i] == 'I' { +func diStringMatch(s string) (ans []int) { + low, high := 0, len(s) + for _, c := range s { + if c == 'I' { ans = append(ans, low) low++ } else { @@ -12,5 +10,5 @@ func diStringMatch(s string) []int { } } ans = append(ans, low) - return ans + return } \ No newline at end of file diff --git a/solution/0900-0999/0942.DI String Match/Solution.py b/solution/0900-0999/0942.DI String Match/Solution.py index 43e458784fa0f..6f990c8da6c94 100644 --- a/solution/0900-0999/0942.DI String Match/Solution.py +++ b/solution/0900-0999/0942.DI String Match/Solution.py @@ -1,10 +1,9 @@ class Solution: def diStringMatch(self, s: str) -> List[int]: - n = len(s) - low, high = 0, n + low, high = 0, len(s) ans = [] - for i in range(n): - if s[i] == 'I': + for c in s: + if c == "I": ans.append(low) low += 1 else: diff --git a/solution/0900-0999/0942.DI String Match/Solution.rs b/solution/0900-0999/0942.DI String Match/Solution.rs index 3b1d3b05b7987..a43b09586c373 100644 --- a/solution/0900-0999/0942.DI String Match/Solution.rs +++ b/solution/0900-0999/0942.DI String Match/Solution.rs @@ -1,19 +1,20 @@ impl Solution { pub fn di_string_match(s: String) -> Vec { - let s = s.as_bytes(); - let n = s.len(); - let mut res = Vec::with_capacity(n + 1); - let (mut low, mut high) = (-1, (n + 1) as i32); - for i in 0..n { - res.push(if s[i] == b'I' { + let mut low = 0; + let mut high = s.len() as i32; + let mut ans = Vec::with_capacity(s.len() + 1); + + for c in s.chars() { + if c == 'I' { + ans.push(low); low += 1; - low } else { + ans.push(high); high -= 1; - high - }); + } } - res.push(low + 1); - res + + ans.push(low); + ans } } diff --git a/solution/0900-0999/0942.DI String Match/Solution.ts b/solution/0900-0999/0942.DI String Match/Solution.ts index eada064c1d1c0..e1971d829eed0 100644 --- a/solution/0900-0999/0942.DI String Match/Solution.ts +++ b/solution/0900-0999/0942.DI String Match/Solution.ts @@ -1,15 +1,13 @@ function diStringMatch(s: string): number[] { - const n = s.length; - const res = new Array(n + 1); - let low = 0; - let high = n; - for (let i = 0; i < n; i++) { - if (s[i] === 'I') { - res[i] = low++; + const ans: number[] = []; + let [low, high] = [0, s.length]; + for (const c of s) { + if (c === 'I') { + ans.push(low++); } else { - res[i] = high--; + ans.push(high--); } } - res[n] = low; - return res; + ans.push(low); + return ans; } diff --git a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/README.md b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/README.md index 2773842cd50b6..e0ccd81563a30 100644 --- a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/README.md +++ b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/README.md @@ -82,21 +82,6 @@ tags: #### Python3 -```python -class Solution: - def smallestDivisor(self, nums: List[int], threshold: int) -> int: - l, r = 1, max(nums) - while l < r: - mid = (l + r) >> 1 - if sum((x + mid - 1) // mid for x in nums) <= threshold: - r = mid - else: - l = mid + 1 - return l -``` - -#### Python3 - ```python class Solution: def smallestDivisor(self, nums: List[int], threshold: int) -> int: @@ -159,7 +144,7 @@ public: ```go func smallestDivisor(nums []int, threshold int) int { - return sort.Search(1000000, func(v int) bool { + return sort.Search(slices.Max(nums), func(v int) bool { v++ s := 0 for _, x := range nums { @@ -178,10 +163,7 @@ function smallestDivisor(nums: number[], threshold: number): number { let r = Math.max(...nums); while (l < r) { const mid = (l + r) >> 1; - let s = 0; - for (const x of nums) { - s += Math.ceil(x / mid); - } + const s = nums.reduce((acc, x) => acc + Math.ceil(x / mid), 0); if (s <= threshold) { r = mid; } else { @@ -192,6 +174,27 @@ function smallestDivisor(nums: number[], threshold: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn smallest_divisor(nums: Vec, threshold: i32) -> i32 { + let mut l = 1; + let mut r = *nums.iter().max().unwrap(); + while l < r { + let mid = (l + r) / 2; + let s: i32 = nums.iter().map(|&x| (x + mid - 1) / mid).sum(); + if s <= threshold { + r = mid; + } else { + l = mid + 1; + } + } + l + } +} +``` + #### JavaScript ```js @@ -205,10 +208,7 @@ var smallestDivisor = function (nums, threshold) { let r = Math.max(...nums); while (l < r) { const mid = (l + r) >> 1; - let s = 0; - for (const x of nums) { - s += Math.ceil(x / mid); - } + const s = nums.reduce((acc, x) => acc + Math.ceil(x / mid), 0); if (s <= threshold) { r = mid; } else { diff --git a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/README_EN.md b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/README_EN.md index 8699548f95875..75df80db43d59 100644 --- a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/README_EN.md +++ b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/README_EN.md @@ -71,21 +71,6 @@ The time complexity is $O(n \times \log M)$, where $n$ is the length of the arra #### Python3 -```python -class Solution: - def smallestDivisor(self, nums: List[int], threshold: int) -> int: - l, r = 1, max(nums) - while l < r: - mid = (l + r) >> 1 - if sum((x + mid - 1) // mid for x in nums) <= threshold: - r = mid - else: - l = mid + 1 - return l -``` - -#### Python3 - ```python class Solution: def smallestDivisor(self, nums: List[int], threshold: int) -> int: @@ -148,7 +133,7 @@ public: ```go func smallestDivisor(nums []int, threshold int) int { - return sort.Search(1000000, func(v int) bool { + return sort.Search(slices.Max(nums), func(v int) bool { v++ s := 0 for _, x := range nums { @@ -167,10 +152,7 @@ function smallestDivisor(nums: number[], threshold: number): number { let r = Math.max(...nums); while (l < r) { const mid = (l + r) >> 1; - let s = 0; - for (const x of nums) { - s += Math.ceil(x / mid); - } + const s = nums.reduce((acc, x) => acc + Math.ceil(x / mid), 0); if (s <= threshold) { r = mid; } else { @@ -181,6 +163,27 @@ function smallestDivisor(nums: number[], threshold: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn smallest_divisor(nums: Vec, threshold: i32) -> i32 { + let mut l = 1; + let mut r = *nums.iter().max().unwrap(); + while l < r { + let mid = (l + r) / 2; + let s: i32 = nums.iter().map(|&x| (x + mid - 1) / mid).sum(); + if s <= threshold { + r = mid; + } else { + l = mid + 1; + } + } + l + } +} +``` + #### JavaScript ```js @@ -194,10 +197,7 @@ var smallestDivisor = function (nums, threshold) { let r = Math.max(...nums); while (l < r) { const mid = (l + r) >> 1; - let s = 0; - for (const x of nums) { - s += Math.ceil(x / mid); - } + const s = nums.reduce((acc, x) => acc + Math.ceil(x / mid), 0); if (s <= threshold) { r = mid; } else { diff --git a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.go b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.go index 4083ffbff34d7..e32a73b754134 100644 --- a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.go +++ b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.go @@ -1,5 +1,5 @@ func smallestDivisor(nums []int, threshold int) int { - return sort.Search(1000000, func(v int) bool { + return sort.Search(slices.Max(nums), func(v int) bool { v++ s := 0 for _, x := range nums { diff --git a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.js b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.js index 68c7d7da08a48..7f95726d9453f 100644 --- a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.js +++ b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.js @@ -8,10 +8,7 @@ var smallestDivisor = function (nums, threshold) { let r = Math.max(...nums); while (l < r) { const mid = (l + r) >> 1; - let s = 0; - for (const x of nums) { - s += Math.ceil(x / mid); - } + const s = nums.reduce((acc, x) => acc + Math.ceil(x / mid), 0); if (s <= threshold) { r = mid; } else { diff --git a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.py b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.py index 8f9a9fe607214..d93ecd44d43ab 100644 --- a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.py +++ b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.py @@ -1,10 +1,7 @@ class Solution: def smallestDivisor(self, nums: List[int], threshold: int) -> int: - l, r = 1, max(nums) - while l < r: - mid = (l + r) >> 1 - if sum((x + mid - 1) // mid for x in nums) <= threshold: - r = mid - else: - l = mid + 1 - return l + def f(v: int) -> bool: + v += 1 + return sum((x + v - 1) // v for x in nums) <= threshold + + return bisect_left(range(max(nums)), True, key=f) + 1 diff --git a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.rs b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.rs new file mode 100644 index 0000000000000..d7a4b2ff1940d --- /dev/null +++ b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.rs @@ -0,0 +1,16 @@ +impl Solution { + pub fn smallest_divisor(nums: Vec, threshold: i32) -> i32 { + let mut l = 1; + let mut r = *nums.iter().max().unwrap(); + while l < r { + let mid = (l + r) / 2; + let s: i32 = nums.iter().map(|&x| (x + mid - 1) / mid).sum(); + if s <= threshold { + r = mid; + } else { + l = mid + 1; + } + } + l + } +} diff --git a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.ts b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.ts index aa20aa28f590f..8309c7cf54088 100644 --- a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.ts +++ b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution.ts @@ -3,10 +3,7 @@ function smallestDivisor(nums: number[], threshold: number): number { let r = Math.max(...nums); while (l < r) { const mid = (l + r) >> 1; - let s = 0; - for (const x of nums) { - s += Math.ceil(x / mid); - } + const s = nums.reduce((acc, x) => acc + Math.ceil(x / mid), 0); if (s <= threshold) { r = mid; } else { diff --git a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution2.py b/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution2.py deleted file mode 100644 index d93ecd44d43ab..0000000000000 --- a/solution/1200-1299/1283.Find the Smallest Divisor Given a Threshold/Solution2.py +++ /dev/null @@ -1,7 +0,0 @@ -class Solution: - def smallestDivisor(self, nums: List[int], threshold: int) -> int: - def f(v: int) -> bool: - v += 1 - return sum((x + v - 1) // v for x in nums) <= threshold - - return bisect_left(range(max(nums)), True, key=f) + 1 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..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 @@ -83,60 +83,17 @@ tags: ### 方法一:二分查找 -二分枚举速度值,找到满足条件的最小速度。 +我们注意到,如果一个速度值 $v$ 能够使得我们在规定时间内到达,那么对于任意 $v' > v$,我们也一定能在规定时间内到达。这存在着单调性,因此我们可以使用二分查找,找到最小的满足条件的速度值。 -时间复杂度 $O(n\times \log m)$,其中 $n$ 和 $m$ 分别为数组 `dist` 和最大速度值。 +在二分查找之前,我们需要先判断是否有可能在规定时间内到达。如果列车数量大于向上取整的规定时间,那么一定无法在规定时间内到达,直接返回 $-1$。 -以下是二分查找的两个通用模板: +接下来,我们定义二分的左右边界为 $l = 1$, $r = 10^7 + 1$,然后我们每次取中间值 $\text{mid} = \frac{l + r}{2}$,判断是否满足条件。如果满足条件,我们将右边界移动到 $\text{mid}$,否则将左边界移动到 $\text{mid} + 1$。 -模板 1: +问题转化为判断一个速度值 $v$ 是否能够在规定时间内到达。我们可以遍历每一趟列车,计算每一趟列车的运行时间 $t = \frac{d}{v}$,如果是最后一趟列车,我们直接加上 $t$,否则我们向上取整加上 $t$。最后判断总时间是否小于等于规定时间,如果是则说明满足条件。 -```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; -} -``` +二分结束后,如果左边界超过了 $10^7$,说明无法在规定时间内到达,返回 $-1$,否则返回左边界。 -模板 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 +102,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 +121,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 +155,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 +186,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 +246,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,32 +286,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; + 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 = parseFloat(dist[i]) / speed; - if (i != n - 1) { - cost = Math.ceil(cost); - } - res += cost; - } - return res <= hour; -} ``` 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..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 @@ -81,7 +81,19 @@ 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. + +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. + +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 +102,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 +121,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 +155,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 +186,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 +246,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,32 +286,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; + 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 = parseFloat(dist[i]) / speed; - if (i != n - 1) { - cost = Math.ceil(cost); - } - res += cost; - } - return res <= hour; -} ``` 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 +}; 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 +} 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 +} 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..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 = parseFloat(dist[i]) / speed; - if (i != n - 1) { - cost = Math.ceil(cost); - } - res += cost; - } - return res <= hour; -} 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 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 } } 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..03752f4c030e5 --- /dev/null +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/Solution.ts @@ -0,0 +1,25 @@ +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; +} diff --git a/solution/2000-2099/2073.Time Needed to Buy Tickets/README.md b/solution/2000-2099/2073.Time Needed to Buy Tickets/README.md index b3140552550b1..4b7367038f07d 100644 --- a/solution/2000-2099/2073.Time Needed to Buy Tickets/README.md +++ b/solution/2000-2099/2073.Time Needed to Buy Tickets/README.md @@ -67,7 +67,13 @@ tags: -### 方法一 +### 方法一:一次遍历 + +根据题目描述,当第 $k$ 个人完成购票时,在第 $k$ 个人前面的所有人,购买的票数都不会超过第 $k$ 个人购买的票数,而在第 $k$ 个人后面的所有人,购买的票数都不会超过第 $k$ 个人购买的票数减 $1$。 + +因此,我们可以遍历整个队伍,对于第 $i$ 个人,如果 $i \leq k$,购票时间为 $\min(\text{tickets}[i], \text{tickets}[k])$,否则购票时间为 $\min(\text{tickets}[i], \text{tickets}[k] - 1)$。我们将所有人的购票时间相加即可。 + +时间复杂度 $O(n)$,其中 $n$ 为队伍的长度。空间复杂度 $O(1)$。 @@ -77,11 +83,8 @@ tags: class Solution: def timeRequiredToBuy(self, tickets: List[int], k: int) -> int: ans = 0 - for i, t in enumerate(tickets): - if i <= k: - ans += min(tickets[k], t) - else: - ans += min(tickets[k] - 1, t) + for i, x in enumerate(tickets): + ans += min(x, tickets[k] if i <= k else tickets[k] - 1) return ans ``` @@ -91,12 +94,8 @@ class Solution: class Solution { public int timeRequiredToBuy(int[] tickets, int k) { int ans = 0; - for (int i = 0; i < tickets.length; i++) { - if (i <= k) { - ans += Math.min(tickets[k], tickets[i]); - } else { - ans += Math.min(tickets[k] - 1, tickets[i]); - } + for (int i = 0; i < tickets.length; ++i) { + ans += Math.min(tickets[i], i <= k ? tickets[k] : tickets[k] - 1); } return ans; } @@ -111,11 +110,7 @@ public: int timeRequiredToBuy(vector& tickets, int k) { int ans = 0; for (int i = 0; i < tickets.size(); ++i) { - if (i <= k) { - ans += min(tickets[k], tickets[i]); - } else { - ans += min(tickets[k] - 1, tickets[i]); - } + ans += min(tickets[i], i <= k ? tickets[k] : tickets[k] - 1); } return ans; } @@ -125,16 +120,15 @@ public: #### Go ```go -func timeRequiredToBuy(tickets []int, k int) int { - ans := 0 - for i, t := range tickets { - if i <= k { - ans += min(tickets[k], t) - } else { - ans += min(tickets[k]-1, t) +func timeRequiredToBuy(tickets []int, k int) (ans int) { + for i, x := range tickets { + t := tickets[k] + if i > k { + t-- } + ans += min(x, t) } - return ans + return } ``` @@ -142,25 +136,10 @@ func timeRequiredToBuy(tickets []int, k int) int { ```ts function timeRequiredToBuy(tickets: number[], k: number): number { - const n = tickets.length; - let target = tickets[k] - 1; let ans = 0; - // round1 - for (let i = 0; i < n; i++) { - let num = tickets[i]; - if (num <= target) { - ans += num; - tickets[i] = 0; - } else { - ans += target; - tickets[i] -= target; - } - } - - // round2 - for (let i = 0; i <= k; i++) { - let num = tickets[i]; - ans += num > 0 ? 1 : 0; + const n = tickets.length; + for (let i = 0; i < n; ++i) { + ans += Math.min(tickets[i], i <= k ? tickets[k] : tickets[k] - 1); } return ans; } diff --git a/solution/2000-2099/2073.Time Needed to Buy Tickets/README_EN.md b/solution/2000-2099/2073.Time Needed to Buy Tickets/README_EN.md index 97d6d1f99895e..ef0f47936e57a 100644 --- a/solution/2000-2099/2073.Time Needed to Buy Tickets/README_EN.md +++ b/solution/2000-2099/2073.Time Needed to Buy Tickets/README_EN.md @@ -67,7 +67,13 @@ The person at position 0 has successfully bought 5 tickets and it took 4 + -### Solution 1 +### Solution 1: Single Pass + +According to the problem description, when the $k^{th}$ person finishes buying tickets, all the people in front of the $k^{th}$ person will not buy more tickets than the $k^{th}$ person, and all the people behind the $k^{th}$ person will not buy more tickets than the $k^{th}$ person minus $1$. + +Therefore, we can traverse the entire queue. For the $i^{th}$ person, if $i \leq k$, the time to buy tickets is $\min(\text{tickets}[i], \text{tickets}[k])$; otherwise, the time to buy tickets is $\min(\text{tickets}[i], \text{tickets}[k] - 1)$. We sum the buying time for all people to get the result. + +The time complexity is $O(n)$, where $n$ is the length of the queue. The space complexity is $O(1)$. @@ -77,11 +83,8 @@ The person at position 0 has successfully bought 5 tickets and it took 4 + class Solution: def timeRequiredToBuy(self, tickets: List[int], k: int) -> int: ans = 0 - for i, t in enumerate(tickets): - if i <= k: - ans += min(tickets[k], t) - else: - ans += min(tickets[k] - 1, t) + for i, x in enumerate(tickets): + ans += min(x, tickets[k] if i <= k else tickets[k] - 1) return ans ``` @@ -91,12 +94,8 @@ class Solution: class Solution { public int timeRequiredToBuy(int[] tickets, int k) { int ans = 0; - for (int i = 0; i < tickets.length; i++) { - if (i <= k) { - ans += Math.min(tickets[k], tickets[i]); - } else { - ans += Math.min(tickets[k] - 1, tickets[i]); - } + for (int i = 0; i < tickets.length; ++i) { + ans += Math.min(tickets[i], i <= k ? tickets[k] : tickets[k] - 1); } return ans; } @@ -111,11 +110,7 @@ public: int timeRequiredToBuy(vector& tickets, int k) { int ans = 0; for (int i = 0; i < tickets.size(); ++i) { - if (i <= k) { - ans += min(tickets[k], tickets[i]); - } else { - ans += min(tickets[k] - 1, tickets[i]); - } + ans += min(tickets[i], i <= k ? tickets[k] : tickets[k] - 1); } return ans; } @@ -125,16 +120,15 @@ public: #### Go ```go -func timeRequiredToBuy(tickets []int, k int) int { - ans := 0 - for i, t := range tickets { - if i <= k { - ans += min(tickets[k], t) - } else { - ans += min(tickets[k]-1, t) +func timeRequiredToBuy(tickets []int, k int) (ans int) { + for i, x := range tickets { + t := tickets[k] + if i > k { + t-- } + ans += min(x, t) } - return ans + return } ``` @@ -142,25 +136,10 @@ func timeRequiredToBuy(tickets []int, k int) int { ```ts function timeRequiredToBuy(tickets: number[], k: number): number { - const n = tickets.length; - let target = tickets[k] - 1; let ans = 0; - // round1 - for (let i = 0; i < n; i++) { - let num = tickets[i]; - if (num <= target) { - ans += num; - tickets[i] = 0; - } else { - ans += target; - tickets[i] -= target; - } - } - - // round2 - for (let i = 0; i <= k; i++) { - let num = tickets[i]; - ans += num > 0 ? 1 : 0; + const n = tickets.length; + for (let i = 0; i < n; ++i) { + ans += Math.min(tickets[i], i <= k ? tickets[k] : tickets[k] - 1); } return ans; } diff --git a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.cpp b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.cpp index 03b07970f1918..25cf0315b56c6 100644 --- a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.cpp +++ b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.cpp @@ -3,11 +3,7 @@ class Solution { int timeRequiredToBuy(vector& tickets, int k) { int ans = 0; for (int i = 0; i < tickets.size(); ++i) { - if (i <= k) { - ans += min(tickets[k], tickets[i]); - } else { - ans += min(tickets[k] - 1, tickets[i]); - } + ans += min(tickets[i], i <= k ? tickets[k] : tickets[k] - 1); } return ans; } diff --git a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.go b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.go index 3a2df57169c91..5beec9e70c958 100644 --- a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.go +++ b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.go @@ -1,11 +1,10 @@ -func timeRequiredToBuy(tickets []int, k int) int { - ans := 0 - for i, t := range tickets { - if i <= k { - ans += min(tickets[k], t) - } else { - ans += min(tickets[k]-1, t) +func timeRequiredToBuy(tickets []int, k int) (ans int) { + for i, x := range tickets { + t := tickets[k] + if i > k { + t-- } + ans += min(x, t) } - return ans + return } \ No newline at end of file diff --git a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.java b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.java index f9c6f7d7394c1..cc09fe2ffcd8a 100644 --- a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.java +++ b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.java @@ -1,12 +1,8 @@ class Solution { public int timeRequiredToBuy(int[] tickets, int k) { int ans = 0; - for (int i = 0; i < tickets.length; i++) { - if (i <= k) { - ans += Math.min(tickets[k], tickets[i]); - } else { - ans += Math.min(tickets[k] - 1, tickets[i]); - } + for (int i = 0; i < tickets.length; ++i) { + ans += Math.min(tickets[i], i <= k ? tickets[k] : tickets[k] - 1); } return ans; } diff --git a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.py b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.py index 24344368f33a7..3b70e0f483c8b 100644 --- a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.py +++ b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.py @@ -1,9 +1,6 @@ class Solution: def timeRequiredToBuy(self, tickets: List[int], k: int) -> int: ans = 0 - for i, t in enumerate(tickets): - if i <= k: - ans += min(tickets[k], t) - else: - ans += min(tickets[k] - 1, t) + for i, x in enumerate(tickets): + ans += min(x, tickets[k] if i <= k else tickets[k] - 1) return ans diff --git a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.ts b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.ts index dace448f9e08a..bced26d419c00 100644 --- a/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.ts +++ b/solution/2000-2099/2073.Time Needed to Buy Tickets/Solution.ts @@ -1,23 +1,8 @@ function timeRequiredToBuy(tickets: number[], k: number): number { - const n = tickets.length; - let target = tickets[k] - 1; let ans = 0; - // round1 - for (let i = 0; i < n; i++) { - let num = tickets[i]; - if (num <= target) { - ans += num; - tickets[i] = 0; - } else { - ans += target; - tickets[i] -= target; - } - } - - // round2 - for (let i = 0; i <= k; i++) { - let num = tickets[i]; - ans += num > 0 ? 1 : 0; + const n = tickets.length; + for (let i = 0; i < n; ++i) { + ans += Math.min(tickets[i], i <= k ? tickets[k] : tickets[k] - 1); } return ans; }