From 3a97bdaccbc577c51d4ed900e97b29758d97cf75 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Wed, 2 Apr 2025 20:40:49 +0800 Subject: [PATCH] feat: add solutions to lc problems: No.1899,1918 * No.1899.Merge Triplets to Form Target Triplet * No.1918.Kth Smallest Subarray Sum --- .../README.md | 59 +++++++- .../README_EN.md | 61 ++++++++- .../Solution.rs | 18 +++ .../Solution.scala | 16 +++ .../1918.Kth Smallest Subarray Sum/README.md | 117 +++++++++++++++- .../README_EN.md | 127 +++++++++++++++++- .../Solution.rs | 30 +++++ .../Solution.scala | 34 +++++ .../Solution.ts | 30 +++++ 9 files changed, 482 insertions(+), 10 deletions(-) create mode 100644 solution/1800-1899/1899.Merge Triplets to Form Target Triplet/Solution.rs create mode 100644 solution/1800-1899/1899.Merge Triplets to Form Target Triplet/Solution.scala create mode 100644 solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.rs create mode 100644 solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.scala create mode 100644 solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.ts diff --git a/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/README.md b/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/README.md index 0119a877c17ed..b9a10353987c1 100644 --- a/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/README.md +++ b/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/README.md @@ -92,13 +92,20 @@ tags: ### 方法一:贪心 -我们记 $target = [x, y, z]$,初始时 $d = e = f = 0$,表示当前的 $a, b, c$ 的最大值。 +我们记 $\textit{target} = [x, y, z]$,我们需要判断是否存在三元组 $[a, b, c]$ 使得 $a \le x, b \le y, c \le z$。 -我们遍历数组 $triplets$,对于每个三元组 $[a, b, c]$,如果 $a \le x, b \le y, c \le z$,则将 $d, e, f$ 分别更新为 $max(d, a), max(e, b), max(f, c)$。 +我们可以将所有的三元组分为两类: -最后判断 $[d, e, f]$ 是否等于 $target$ 即可。 +1. 满足 $a \le x, b \le y, c \le z$ 的三元组。 +2. 不满足 $a \le x, b \le y, c \le z$ 的三元组。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $triplets$ 的长度。 +对于第一类三元组,我们可以将它们的 $a, b, c$ 分别取最大值,得到一个新的三元组 $[d, e, f]$。 + +对于第二类三元组,我们可以忽略它们,因为它们无法帮助我们得到目标三元组。 + +最后,我们只需要判断 $[d, e, f]$ 是否等于 $\textit{target}$ 即可。如果等于,返回 $\textit{true}$,否则返回 $\textit{false}$。 + +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{triplets}$ 的长度。空间复杂度 $O(1)$。 @@ -193,6 +200,50 @@ function mergeTriplets(triplets: number[][], target: number[]): boolean { } ``` +#### Rust + +```rust +impl Solution { + pub fn merge_triplets(triplets: Vec>, target: Vec) -> bool { + let [x, y, z]: [i32; 3] = target.try_into().unwrap(); + let (mut d, mut e, mut f) = (0, 0, 0); + + for triplet in triplets { + if let [a, b, c] = triplet[..] { + if a <= x && b <= y && c <= z { + d = d.max(a); + e = e.max(b); + f = f.max(c); + } + } + } + + [d, e, f] == [x, y, z] + } +} +``` + +#### Scala + +```scala +object Solution { + def mergeTriplets(triplets: Array[Array[Int]], target: Array[Int]): Boolean = { + val Array(x, y, z) = target + var (d, e, f) = (0, 0, 0) + + for (Array(a, b, c) <- triplets) { + if (a <= x && b <= y && c <= z) { + d = d.max(a) + e = e.max(b) + f = f.max(c) + } + } + + d == x && e == y && f == z + } +} +``` + diff --git a/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/README_EN.md b/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/README_EN.md index 90a6d318161dd..688ff33ca0307 100644 --- a/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/README_EN.md +++ b/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/README_EN.md @@ -80,7 +80,22 @@ The target triplet [5,5,5] is now an element of triplets. -### Solution 1 +### Solution 1: Greedy + +Let $\textit{target} = [x, y, z]$. We need to determine whether there exists a triplet $[a, b, c]$ such that $a \leq x$, $b \leq y$, and $c \leq z$. + +We can divide all triplets into two categories: + +1. Triplets that satisfy $a \leq x$, $b \leq y$, and $c \leq z$. +2. Triplets that do not satisfy $a \leq x$, $b \leq y$, and $c \leq z$. + +For the first category, we can take the maximum values of $a$, $b$, and $c$ from these triplets to form a new triplet $[d, e, f]$. + +For the second category, we can ignore these triplets because they cannot help us achieve the target triplet. + +Finally, we just need to check whether $[d, e, f]$ is equal to $\textit{target}$. If it is, return $\textit{true}$; otherwise, return $\textit{false}$. + +Time complexity is $O(n)$, where $n$ is the length of the array $\textit{triplets}$. Space complexity is $O(1)$. @@ -175,6 +190,50 @@ function mergeTriplets(triplets: number[][], target: number[]): boolean { } ``` +#### Rust + +```rust +impl Solution { + pub fn merge_triplets(triplets: Vec>, target: Vec) -> bool { + let [x, y, z]: [i32; 3] = target.try_into().unwrap(); + let (mut d, mut e, mut f) = (0, 0, 0); + + for triplet in triplets { + if let [a, b, c] = triplet[..] { + if a <= x && b <= y && c <= z { + d = d.max(a); + e = e.max(b); + f = f.max(c); + } + } + } + + [d, e, f] == [x, y, z] + } +} +``` + +#### Scala + +```scala +object Solution { + def mergeTriplets(triplets: Array[Array[Int]], target: Array[Int]): Boolean = { + val Array(x, y, z) = target + var (d, e, f) = (0, 0, 0) + + for (Array(a, b, c) <- triplets) { + if (a <= x && b <= y && c <= z) { + d = d.max(a) + e = e.max(b) + f = f.max(c) + } + } + + d == x && e == y && f == z + } +} +``` + diff --git a/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/Solution.rs b/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/Solution.rs new file mode 100644 index 0000000000000..1a96b4b301e98 --- /dev/null +++ b/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/Solution.rs @@ -0,0 +1,18 @@ +impl Solution { + pub fn merge_triplets(triplets: Vec>, target: Vec) -> bool { + let [x, y, z]: [i32; 3] = target.try_into().unwrap(); + let (mut d, mut e, mut f) = (0, 0, 0); + + for triplet in triplets { + if let [a, b, c] = triplet[..] { + if a <= x && b <= y && c <= z { + d = d.max(a); + e = e.max(b); + f = f.max(c); + } + } + } + + [d, e, f] == [x, y, z] + } +} diff --git a/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/Solution.scala b/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/Solution.scala new file mode 100644 index 0000000000000..dacd89c145f05 --- /dev/null +++ b/solution/1800-1899/1899.Merge Triplets to Form Target Triplet/Solution.scala @@ -0,0 +1,16 @@ +object Solution { + def mergeTriplets(triplets: Array[Array[Int]], target: Array[Int]): Boolean = { + val Array(x, y, z) = target + var (d, e, f) = (0, 0, 0) + + for (Array(a, b, c) <- triplets) { + if (a <= x && b <= y && c <= z) { + d = d.max(a) + e = e.max(b) + f = f.max(c) + } + } + + d == x && e == y && f == z + } +} \ No newline at end of file diff --git a/solution/1900-1999/1918.Kth Smallest Subarray Sum/README.md b/solution/1900-1999/1918.Kth Smallest Subarray Sum/README.md index 8fafc58f2d6fd..88b7d91d87ab3 100644 --- a/solution/1900-1999/1918.Kth Smallest Subarray Sum/README.md +++ b/solution/1900-1999/1918.Kth Smallest Subarray Sum/README.md @@ -79,19 +79,19 @@ tags: 我们注意到,题目中数组元素均为正整数,子数组的和 $s$ 越大,那么数组中子数组和小于等于 $s$ 的个数就越多。这存在一个单调性,因此我们可以考虑使用使用二分查找的方法来求解。 -我们二分枚举子数组的和,初始化左右边界分别为数组 $nums$ 中的最小值以及所有元素之和。每次我们计算数组中子数组和小于等于当前枚举值的个数,如果个数大于等于 $k$,则说明当前枚举值 $s$ 可能是第 $k$ 小的子数组和,我们缩小右边界,否则我们增大左边界。枚举结束后,左边界即为第 $k$ 小的子数组和。 +我们二分枚举子数组的和,初始化左右边界分别为数组 $\textit{nums}$ 中的最小值以及所有元素之和。每次我们计算数组中子数组和小于等于当前枚举值的个数,如果个数大于等于 $k$,则说明当前枚举值 $s$ 可能是第 $k$ 小的子数组和,我们缩小右边界,否则我们增大左边界。枚举结束后,左边界即为第 $k$ 小的子数组和。 问题转换为计算一个数组中,有多少个子数组的和小于等于 $s$,我们可以通过函数 $f(s)$ 来计算。 函数 $f(s)$ 的计算方法如下: - 初始化双指针 $j$ 和 $i$,分别指向当前窗口的左右边界,初始时 $j = i = 0$。初始化窗口内元素的和 $t = 0$。 -- 用变量 $cnt$ 记录子数组和小于等于 $s$ 的个数,初始时 $cnt = 0$。 -- 遍历数组 $nums$,每次遍历到一个元素 $nums[i]$,我们将其加入窗口,即 $t = t + nums[i]$。如果此时 $t \gt s$,我们需要不断地将窗口的左边界右移,直到 $t \le s$ 为止,即不断地执行 $t -= nums[j]$,并且 $j = j + 1$。接下来我们更新 $cnt$,即 $cnt = cnt + i - j + 1$。继续遍历下一个元素,直到遍历完整个数组。 +- 用变量 $\textit{cnt}$ 记录子数组和小于等于 $s$ 的个数,初始时 $\textit{cnt} = 0$。 +- 遍历数组 $\textit{nums}$,每次遍历到一个元素 $\textit{nums}[i]$,我们将其加入窗口,即 $t = t + \textit{nums}[i]$。如果此时 $t \gt s$,我们需要不断地将窗口的左边界右移,直到 $t \le s$ 为止,即不断地执行 $t -= \textit{nums}[j]$,并且 $j = j + 1$。接下来我们更新 $\textit{cnt}$,即 $\textit{cnt} = \textit{cnt} + i - j + 1$。继续遍历下一个元素,直到遍历完整个数组。 最后将 $cnt$ 作为函数 $f(s)$ 的返回值。 -时间复杂度 $O(n \times \log S)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度,而 $S$ 为数组 $nums$ 中所有元素之和。 +时间复杂度 $O(n \times \log S)$,其中 $n$ 为数组 $\textit{nums}$ 的长度,而 $S$ 为数组 $\textit{nums}$ 中所有元素之和。空间复杂度 $O(1)$。 @@ -219,6 +219,115 @@ func kthSmallestSubarraySum(nums []int, k int) int { } ``` +#### TypeScript + +```ts +function kthSmallestSubarraySum(nums: number[], k: number): number { + let l = Math.min(...nums); + let r = nums.reduce((sum, x) => sum + x, 0); + + const f = (s: number): number => { + let cnt = 0; + let t = 0; + let j = 0; + + for (let i = 0; i < nums.length; i++) { + t += nums[i]; + while (t > s) { + t -= nums[j]; + j++; + } + cnt += i - j + 1; + } + return cnt; + }; + + while (l < r) { + const mid = (l + r) >> 1; + if (f(mid) >= k) { + r = mid; + } else { + l = mid + 1; + } + } + return l; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn kth_smallest_subarray_sum(nums: Vec, k: i32) -> i32 { + let mut l = *nums.iter().min().unwrap(); + let mut r: i32 = nums.iter().sum(); + + let f = |s: i32| -> i32 { + let (mut cnt, mut t, mut j) = (0, 0, 0); + + for i in 0..nums.len() { + t += nums[i]; + while t > s { + t -= nums[j]; + j += 1; + } + cnt += (i - j + 1) as i32; + } + cnt + }; + + while l < r { + let mid = (l + r) / 2; + if f(mid) >= k { + r = mid; + } else { + l = mid + 1; + } + } + l + } +} +``` + +#### Scala + +```scala +object Solution { + def kthSmallestSubarraySum(nums: Array[Int], k: Int): Int = { + var l = Int.MaxValue + var r = 0 + + for (x <- nums) { + l = l.min(x) + r += x + } + + def f(s: Int): Int = { + var cnt = 0 + var t = 0 + var j = 0 + + for (i <- nums.indices) { + t += nums(i) + while (t > s) { + t -= nums(j) + j += 1 + } + cnt += i - j + 1 + } + cnt + } + + while (l < r) { + val mid = (l + r) / 2 + if (f(mid) >= k) r = mid + else l = mid + 1 + } + l + } +} +``` + diff --git a/solution/1900-1999/1918.Kth Smallest Subarray Sum/README_EN.md b/solution/1900-1999/1918.Kth Smallest Subarray Sum/README_EN.md index 5048063fda753..4097ad5be33a8 100644 --- a/solution/1900-1999/1918.Kth Smallest Subarray Sum/README_EN.md +++ b/solution/1900-1999/1918.Kth Smallest Subarray Sum/README_EN.md @@ -73,7 +73,23 @@ Ordering the sums from smallest to largest gives 3, 3, 5, 5, 6, 8, 10, 11 -### Solution 1 +### Solution 1: Binary Search + Two Pointers + +We observe that all elements in the array are positive integers. The larger the subarray sum $s$, the more subarrays there are with sums less than or equal to $s$. This monotonicity allows us to use binary search to solve the problem. + +We perform binary search on the subarray sum, initializing the left and right boundaries as the minimum value in the array $\textit{nums}$ and the sum of all elements in the array, respectively. Each time, we calculate the number of subarrays with sums less than or equal to the current middle value. If the count is greater than or equal to $k$, it means the current middle value $s$ might be the $k$-th smallest subarray sum, so we shrink the right boundary. Otherwise, we increase the left boundary. After the binary search ends, the left boundary will be the $k$-th smallest subarray sum. + +The problem reduces to calculating the number of subarrays in an array with sums less than or equal to $s$, which we can compute using a function $f(s)$. + +The function $f(s)$ is calculated as follows: + +- Initialize two pointers $j$ and $i$, representing the left and right boundaries of the current window, with $j = i = 0$. Also, initialize the sum of elements in the window $t = 0$. +- Use a variable $\textit{cnt}$ to record the number of subarrays with sums less than or equal to $s$, initially $\textit{cnt} = 0$. +- Traverse the array $\textit{nums}$. For each element $\textit{nums}[i]$, add it to the window, i.e., $t = t + \textit{nums}[i]$. If $t > s$, move the left boundary of the window to the right until $t \leq s$, i.e., repeatedly execute $t -= \textit{nums}[j]$ and $j = j + 1$. Then update $\textit{cnt}$ as $\textit{cnt} = \textit{cnt} + i - j + 1$. Continue to the next element until the entire array is traversed. + +Finally, return $cnt$ as the result of the function $f(s)$. + +Time complexity is $O(n \times \log S)$, where $n$ is the length of the array $\textit{nums}$, and $S$ is the sum of all elements in the array $\textit{nums}$. Space complexity is $O(1)$. @@ -201,6 +217,115 @@ func kthSmallestSubarraySum(nums []int, k int) int { } ``` +#### Typescript + +```ts +function kthSmallestSubarraySum(nums: number[], k: number): number { + let l = Math.min(...nums); + let r = nums.reduce((sum, x) => sum + x, 0); + + const f = (s: number): number => { + let cnt = 0; + let t = 0; + let j = 0; + + for (let i = 0; i < nums.length; i++) { + t += nums[i]; + while (t > s) { + t -= nums[j]; + j++; + } + cnt += i - j + 1; + } + return cnt; + }; + + while (l < r) { + const mid = (l + r) >> 1; + if (f(mid) >= k) { + r = mid; + } else { + l = mid + 1; + } + } + return l; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn kth_smallest_subarray_sum(nums: Vec, k: i32) -> i32 { + let mut l = *nums.iter().min().unwrap(); + let mut r: i32 = nums.iter().sum(); + + let f = |s: i32| -> i32 { + let (mut cnt, mut t, mut j) = (0, 0, 0); + + for i in 0..nums.len() { + t += nums[i]; + while t > s { + t -= nums[j]; + j += 1; + } + cnt += (i - j + 1) as i32; + } + cnt + }; + + while l < r { + let mid = (l + r) / 2; + if f(mid) >= k { + r = mid; + } else { + l = mid + 1; + } + } + l + } +} +``` + +#### Scala + +```scala +object Solution { + def kthSmallestSubarraySum(nums: Array[Int], k: Int): Int = { + var l = Int.MaxValue + var r = 0 + + for (x <- nums) { + l = l.min(x) + r += x + } + + def f(s: Int): Int = { + var cnt = 0 + var t = 0 + var j = 0 + + for (i <- nums.indices) { + t += nums(i) + while (t > s) { + t -= nums(j) + j += 1 + } + cnt += i - j + 1 + } + cnt + } + + while (l < r) { + val mid = (l + r) / 2 + if (f(mid) >= k) r = mid + else l = mid + 1 + } + l + } +} +``` + diff --git a/solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.rs b/solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.rs new file mode 100644 index 0000000000000..29a056b7d9293 --- /dev/null +++ b/solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.rs @@ -0,0 +1,30 @@ +impl Solution { + pub fn kth_smallest_subarray_sum(nums: Vec, k: i32) -> i32 { + let mut l = *nums.iter().min().unwrap(); + let mut r: i32 = nums.iter().sum(); + + let f = |s: i32| -> i32 { + let (mut cnt, mut t, mut j) = (0, 0, 0); + + for i in 0..nums.len() { + t += nums[i]; + while t > s { + t -= nums[j]; + j += 1; + } + cnt += (i - j + 1) as i32; + } + cnt + }; + + while l < r { + let mid = (l + r) / 2; + if f(mid) >= k { + r = mid; + } else { + l = mid + 1; + } + } + l + } +} diff --git a/solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.scala b/solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.scala new file mode 100644 index 0000000000000..315d952d4ec92 --- /dev/null +++ b/solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.scala @@ -0,0 +1,34 @@ +object Solution { + def kthSmallestSubarraySum(nums: Array[Int], k: Int): Int = { + var l = Int.MaxValue + var r = 0 + + for (x <- nums) { + l = l.min(x) + r += x + } + + def f(s: Int): Int = { + var cnt = 0 + var t = 0 + var j = 0 + + for (i <- nums.indices) { + t += nums(i) + while (t > s) { + t -= nums(j) + j += 1 + } + cnt += i - j + 1 + } + cnt + } + + while (l < r) { + val mid = (l + r) / 2 + if (f(mid) >= k) r = mid + else l = mid + 1 + } + l + } +} diff --git a/solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.ts b/solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.ts new file mode 100644 index 0000000000000..bf27d5bc14673 --- /dev/null +++ b/solution/1900-1999/1918.Kth Smallest Subarray Sum/Solution.ts @@ -0,0 +1,30 @@ +function kthSmallestSubarraySum(nums: number[], k: number): number { + let l = Math.min(...nums); + let r = nums.reduce((sum, x) => sum + x, 0); + + const f = (s: number): number => { + let cnt = 0; + let t = 0; + let j = 0; + + for (let i = 0; i < nums.length; i++) { + t += nums[i]; + while (t > s) { + t -= nums[j]; + j++; + } + cnt += i - j + 1; + } + return cnt; + }; + + while (l < r) { + const mid = (l + r) >> 1; + if (f(mid) >= k) { + r = mid; + } else { + l = mid + 1; + } + } + return l; +}