From 67007cea14b086ccf92dbff91fc900e27ee518fa Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Mon, 16 Jun 2025 04:19:01 +0300 Subject: [PATCH 1/6] Added tasks 3582-3585 --- .../Solution.kt | 38 ++++++ .../readme.md | 51 ++++++++ .../s3583_count_special_triplets/Solution.kt | 23 ++++ .../s3583_count_special_triplets/readme.md | 67 ++++++++++ .../Solution.kt | 20 +++ .../readme.md | 43 ++++++ .../Solution.kt | 122 ++++++++++++++++++ .../readme.md | 70 ++++++++++ .../SolutionTest.kt | 44 +++++++ .../SolutionTest.kt | 28 ++++ .../SolutionTest.kt | 31 +++++ .../SolutionTest.kt | 50 +++++++ 12 files changed, 587 insertions(+) create mode 100644 src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt create mode 100644 src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/readme.md create mode 100644 src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt create mode 100644 src/main/kotlin/g3501_3600/s3583_count_special_triplets/readme.md create mode 100644 src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt create mode 100644 src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/readme.md create mode 100644 src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt create mode 100644 src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/readme.md create mode 100644 src/test/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/SolutionTest.kt create mode 100644 src/test/kotlin/g3501_3600/s3583_count_special_triplets/SolutionTest.kt create mode 100644 src/test/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/SolutionTest.kt create mode 100644 src/test/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/SolutionTest.kt diff --git a/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt b/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt new file mode 100644 index 00000000..65d40a6d --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt @@ -0,0 +1,38 @@ +package g3501_3600.s3582_generate_tag_for_video_caption + +// #Easy #2025_06_16_Time_12_ms_(100.00%)_Space_45.47_MB_(100.00%) + +import java.util.Locale + +class Solution { + fun generateTag(caption: String): String? { + if (caption.trim { it <= ' ' }.isEmpty()) { + return "#" + } + val arr = caption.trim { it <= ' ' }.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + val res = StringBuilder("#") + var firstWord = arr[0] + firstWord = + ( + firstWord.substring(0, 1).lowercase(Locale.getDefault()) + + (if (firstWord.length > 1) firstWord.substring(1).lowercase(Locale.getDefault()) else "") + ) + res.append(firstWord) + for (i in 1.. 1) w.substring(1).lowercase(Locale.getDefault()) else "") + ) + res.append(w) + if (res.length >= 100) { + break + } + } + return if (res.length > 100) res.substring(0, 100) else res.toString() + } +} diff --git a/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/readme.md b/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/readme.md new file mode 100644 index 00000000..d64fccb6 --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/readme.md @@ -0,0 +1,51 @@ +3582\. Generate Tag for Video Caption + +Easy + +You are given a string `caption` representing the caption for a video. + +The following actions must be performed **in order** to generate a **valid tag** for the video: + +1. **Combine all words** in the string into a single _camelCase string_ prefixed with `'#'`. A _camelCase string_ is one where the first letter of all words _except_ the first one is capitalized. All characters after the first character in **each** word must be lowercase. + +2. **Remove** all characters that are not an English letter, **except** the first `'#'`. + +3. **Truncate** the result to a maximum of 100 characters. + + +Return the **tag** after performing the actions on `caption`. + +**Example 1:** + +**Input:** caption = "Leetcode daily streak achieved" + +**Output:** "#leetcodeDailyStreakAchieved" + +**Explanation:** + +The first letter for all words except `"leetcode"` should be capitalized. + +**Example 2:** + +**Input:** caption = "can I Go There" + +**Output:** "#canIGoThere" + +**Explanation:** + +The first letter for all words except `"can"` should be capitalized. + +**Example 3:** + +**Input:** caption = "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" + +**Output:** "#hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" + +**Explanation:** + +Since the first word has length 101, we need to truncate the last two letters from the word. + +**Constraints:** + +* `1 <= caption.length <= 150` +* `caption` consists only of English letters and `' '`. \ No newline at end of file diff --git a/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt b/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt new file mode 100644 index 00000000..217a36e3 --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt @@ -0,0 +1,23 @@ +package g3501_3600.s3583_count_special_triplets + +// #Medium #2025_06_16_Time_250_ms_(100.00%)_Space_62.22_MB_(100.00%) + +class Solution { + fun specialTriplets(nums: IntArray): Int { + val mod = 1000000007 + var res = 0 + val left: MutableMap = HashMap() + val right: MutableMap = HashMap() + for (num in nums) { + right.put(num, right.getOrDefault(num, 0) + 1) + } + for (num in nums) { + right.put(num, right[num]!! - 1) + val ci: Int = left.getOrDefault(num * 2, 0) + val ck: Int = right.getOrDefault(num * 2, 0) + res = (res + ci * ck) % mod + left.put(num, left.getOrDefault(num, 0) + 1) + } + return res + } +} diff --git a/src/main/kotlin/g3501_3600/s3583_count_special_triplets/readme.md b/src/main/kotlin/g3501_3600/s3583_count_special_triplets/readme.md new file mode 100644 index 00000000..3f704fb0 --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3583_count_special_triplets/readme.md @@ -0,0 +1,67 @@ +3583\. Count Special Triplets + +Medium + +You are given an integer array `nums`. + +A **special triplet** is defined as a triplet of indices `(i, j, k)` such that: + +* `0 <= i < j < k < n`, where `n = nums.length` +* `nums[i] == nums[j] * 2` +* `nums[k] == nums[j] * 2` + +Return the total number of **special triplets** in the array. + +Since the answer may be large, return it **modulo** 109 + 7. + +**Example 1:** + +**Input:** nums = [6,3,6] + +**Output:** 1 + +**Explanation:** + +The only special triplet is `(i, j, k) = (0, 1, 2)`, where: + +* `nums[0] = 6`, `nums[1] = 3`, `nums[2] = 6` +* `nums[0] = nums[1] * 2 = 3 * 2 = 6` +* `nums[2] = nums[1] * 2 = 3 * 2 = 6` + +**Example 2:** + +**Input:** nums = [0,1,0,0] + +**Output:** 1 + +**Explanation:** + +The only special triplet is `(i, j, k) = (0, 2, 3)`, where: + +* `nums[0] = 0`, `nums[2] = 0`, `nums[3] = 0` +* `nums[0] = nums[2] * 2 = 0 * 2 = 0` +* `nums[3] = nums[2] * 2 = 0 * 2 = 0` + +**Example 3:** + +**Input:** nums = [8,4,2,8,4] + +**Output:** 2 + +**Explanation:** + +There are exactly two special triplets: + +* `(i, j, k) = (0, 1, 3)` + * `nums[0] = 8`, `nums[1] = 4`, `nums[3] = 8` + * `nums[0] = nums[1] * 2 = 4 * 2 = 8` + * `nums[3] = nums[1] * 2 = 4 * 2 = 8` +* `(i, j, k) = (1, 2, 4)` + * `nums[1] = 4`, `nums[2] = 2`, `nums[4] = 4` + * `nums[1] = nums[2] * 2 = 2 * 2 = 4` + * `nums[4] = nums[2] * 2 = 2 * 2 = 4` + +**Constraints:** + +* 3 <= n == nums.length <= 105 +* 0 <= nums[i] <= 105 \ No newline at end of file diff --git a/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt b/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt new file mode 100644 index 00000000..126b7eea --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt @@ -0,0 +1,20 @@ +package g3501_3600.s3584_maximum_product_of_first_and_last_elements_of_a_subsequence + +// #Medium #2025_06_16_Time_4_ms_(87.17%)_Space_61.31_MB_(100.00%) + +import kotlin.math.max +import kotlin.math.min + +class Solution { + fun maximumProduct(nums: IntArray, m: Int): Long { + var ma = nums[0].toLong() + var mi = nums[0].toLong() + var res = nums[0].toLong() * nums[m - 1] + for (i in m - 1..1 <= nums.length <= 105 +* -105 <= nums[i] <= 105 +* `1 <= m <= nums.length` \ No newline at end of file diff --git a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt new file mode 100644 index 00000000..f7d9fffa --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt @@ -0,0 +1,122 @@ +package g3501_3600.s3585_find_weighted_median_node_in_tree + +// #Hard #2025_06_16_Time_162_ms_(100.00%)_Space_141.58_MB_(100.00%) + +class Solution { + private var log = 0 + private lateinit var dist: LongArray + private lateinit var depth: IntArray + private lateinit var up: Array + + fun findMedian(n: Int, edges: Array, queries: Array): IntArray { + val adj: MutableList?> = ArrayList?>() + for (i in 0..()) + } + for (edge in edges) { + adj[edge[0]]!!.add(intArrayOf(edge[1], edge[2])) + adj[edge[1]]!!.add(intArrayOf(edge[0], edge[2])) + } + dist = LongArray(n) + depth = IntArray(n) + log = 0 + while (1 shl log < n) { + log++ + } + up = Array(n) { IntArray(log) } + for (u in up) { + u.fill(-1) + } + dfs(0, -1, adj, 0, 0) + val ans = IntArray(queries.size) + for (i in queries.indices) { + val query = queries[i] + var first = query[0] + var second = query[1] + val distance = getDistance(first, second) + var needed = (distance + 1) / 2 + val mid = lca(first, second) + if (getDistance(first, mid) < needed) { + needed -= getDistance(first, mid) + first = mid + } else { + second = mid + } + if (depth[first] <= depth[second]) { + var curDistance = getDistance(first, second) + for (j in log - 1 downTo 0) { + if (up[second][j] == -1 || + curDistance - getDistance(up[second][j], second) < needed + ) { + continue + } + curDistance -= getDistance(up[second][j], second) + second = up[second][j] + } + ans[i] = second + } else { + var curDistance: Long = 0 + for (j in log - 1 downTo 0) { + if (up[first][j] == -1 || + curDistance + getDistance(up[first][j], first) >= needed + ) { + continue + } + curDistance += getDistance(up[first][j], first) + first = up[first][j] + } + ans[i] = up[first][0] + } + } + return ans + } + + private fun getDistance(from: Int, to: Int): Long { + if (from == to) { + return 0 + } + val ancesor = lca(from, to) + return dist[from] + dist[to] - 2 * dist[ancesor] + } + + private fun lca(first: Int, second: Int): Int { + var first = first + var second = second + if (depth[first] < depth[second]) { + return lca(second, first) + } + for (i in log - 1 downTo 0) { + if (depth[first] - (1 shl i) >= depth[second]) { + first = up[first][i] + } + } + if (first == second) { + return second + } + for (i in log - 1 downTo 0) { + if (depth[first] != -1 && up[first][i] != up[second][i]) { + first = up[first][i] + second = up[second][i] + } + } + first = up[first][0] + return first + } + + private fun dfs(current: Int, parent: Int, adj: MutableList?>, curDist: Long, curDepth: Int) { + up[current][0] = parent + for (i in 1..edges[i] = [ui, vi, wi] indicates an edge from node ui to vi with weight wi. + +The **weighted median node** is defined as the **first** node `x` on the path from ui to vi such that the sum of edge weights from ui to `x` is **greater than or equal to half** of the total path weight. + +You are given a 2D integer array `queries`. For each queries[j] = [uj, vj], determine the weighted median node along the path from uj to vj. + +Return an array `ans`, where `ans[j]` is the node index of the weighted median for `queries[j]`. + +**Example 1:** + +**Input:** n = 2, edges = [[0,1,7]], queries = [[1,0],[0,1]] + +**Output:** [0,1] + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/05/26/screenshot-2025-05-26-at-193447.png) + +| Query | Path | Edge Weights | Total Path Weight | Half | Explanation | Answer | +|------------|----------|---------------|--------------------|------|-------------------------------------------------------|--------| +| `[1, 0]` | `1 → 0` | `[7]` | 7 | 3.5 | Sum from `1 → 0 = 7 >= 3.5`, median is node 0. | 0 | +| `[0, 1]` | `0 → 1` | `[7]` | 7 | 3.5 | Sum from `0 → 1 = 7 >= 3.5`, median is node 1. | 1 | + + +**Example 2:** + +**Input:** n = 3, edges = [[0,1,2],[2,0,4]], queries = [[0,1],[2,0],[1,2]] + +**Output:** [1,0,2] + +**E****xplanation:** + +![](https://assets.leetcode.com/uploads/2025/05/26/screenshot-2025-05-26-at-193610.png) + +| Query | Path | Edge Weights | Total Path Weight | Half | Explanation | Answer | +|------------|--------------|--------------|--------------------|------|-----------------------------------------------------------------------------|--------| +| `[0, 1]` | `0 → 1` | `[2]` | 2 | 1 | Sum from `0 → 1 = 2 >= 1`, median is node 1. | 1 | +| `[2, 0]` | `2 → 0` | `[4]` | 4 | 2 | Sum from `2 → 0 = 4 >= 2`, median is node 0. | 0 | +| `[1, 2]` | `1 → 0 → 2` | `[2, 4]` | 6 | 3 | Sum from `1 → 0 = 2 < 3`.
Sum from `1 → 2 = 2 + 4 = 6 >= 3`, median is node 2. | 2 | + +**Example 3:** + +**Input:** n = 5, edges = [[0,1,2],[0,2,5],[1,3,1],[2,4,3]], queries = [[3,4],[1,2]] + +**Output:** [2,2] + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/05/26/screenshot-2025-05-26-at-193857.png) + +| Query | Path | Edge Weights | Total Path Weight | Half | Explanation | Answer | +|------------|----------------------|------------------|--------------------|------|-----------------------------------------------------------------------------------------------------------------------------------------------------|--------| +| `[3, 4]` | `3 → 1 → 0 → 2 → 4` | `[1, 2, 5, 3]` | 11 | 5.5 | Sum from `3 → 1 = 1 < 5.5`.
Sum from `3 → 0 = 1 + 2 = 3 < 5.5`.
Sum from `3 → 2 = 1 + 2 + 5 = 8 >= 5.5`, median is node 2. | 2 | +| `[1, 2]` | `1 → 0 → 2` | `[2, 5]` | 7 | 3.5 | Sum from `1 → 0 = 2 < 3.5`.
Sum from `1 → 2 = 2 + 5 = 7 >= 3.5`, median is node 2. | 2 | + +**Constraints:** + +* 2 <= n <= 105 +* `edges.length == n - 1` +* edges[i] == [ui, vi, wi] +* 0 <= ui, vi < n +* 1 <= wi <= 109 +* 1 <= queries.length <= 105 +* queries[j] == [uj, vj] +* 0 <= uj, vj < n +* The input is generated such that `edges` represents a valid tree. \ No newline at end of file diff --git a/src/test/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/SolutionTest.kt b/src/test/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/SolutionTest.kt new file mode 100644 index 00000000..011d7d32 --- /dev/null +++ b/src/test/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/SolutionTest.kt @@ -0,0 +1,44 @@ +package g3501_3600.s3582_generate_tag_for_video_caption + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun generateTag() { + assertThat( + Solution().generateTag("Leetcode daily streak achieved"), + equalTo("#leetcodeDailyStreakAchieved"), + ) + } + + @Test + fun generateTag2() { + assertThat( + Solution().generateTag("can I Go There"), + equalTo("#canIGoThere"), + ) + } + + @Test + fun generateTag3() { + assertThat( + Solution() + .generateTag( + ( + "hhhhhhhhhhhhhhhhhhhhh" + + "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" + + "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" + ), + ), + equalTo( + ( + "#hhhhhhhhhhhhhhhhhhh" + + "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" + + "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" + ), + ), + ) + } +} diff --git a/src/test/kotlin/g3501_3600/s3583_count_special_triplets/SolutionTest.kt b/src/test/kotlin/g3501_3600/s3583_count_special_triplets/SolutionTest.kt new file mode 100644 index 00000000..6725d571 --- /dev/null +++ b/src/test/kotlin/g3501_3600/s3583_count_special_triplets/SolutionTest.kt @@ -0,0 +1,28 @@ +package g3501_3600.s3583_count_special_triplets + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun specialTriplets() { + assertThat(Solution().specialTriplets(intArrayOf(6, 3, 6)), equalTo(1)) + } + + @Test + fun specialTriplets2() { + assertThat( + Solution().specialTriplets(intArrayOf(0, 1, 0, 0)), + equalTo(1), + ) + } + + @Test + fun specialTriplets3() { + assertThat( + Solution().specialTriplets(intArrayOf(8, 4, 2, 8, 4)), + equalTo(2), + ) + } +} diff --git a/src/test/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/SolutionTest.kt b/src/test/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/SolutionTest.kt new file mode 100644 index 00000000..805ce4d5 --- /dev/null +++ b/src/test/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/SolutionTest.kt @@ -0,0 +1,31 @@ +package g3501_3600.s3584_maximum_product_of_first_and_last_elements_of_a_subsequence + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun maximumProduct() { + assertThat( + Solution().maximumProduct(intArrayOf(-1, -9, 2, 3, -2, -3, 1), 1), + equalTo(81L), + ) + } + + @Test + fun maximumProduct2() { + assertThat( + Solution().maximumProduct(intArrayOf(1, 3, -5, 5, 6, -4), 3), + equalTo(20L), + ) + } + + @Test + fun maximumProduct3() { + assertThat( + Solution().maximumProduct(intArrayOf(2, -1, 2, -6, 5, 2, -5, 7), 2), + equalTo(35L), + ) + } +} diff --git a/src/test/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/SolutionTest.kt b/src/test/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/SolutionTest.kt new file mode 100644 index 00000000..bc099c61 --- /dev/null +++ b/src/test/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/SolutionTest.kt @@ -0,0 +1,50 @@ +package g3501_3600.s3585_find_weighted_median_node_in_tree + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun findMedian() { + assertThat( + Solution().findMedian( + 2, + arrayOf(intArrayOf(0, 1, 7)), + arrayOf(intArrayOf(1, 0), intArrayOf(0, 1)), + ), + equalTo(intArrayOf(0, 1)), + ) + } + + @Test + fun findMedian2() { + assertThat( + Solution() + .findMedian( + 3, + arrayOf(intArrayOf(0, 1, 2), intArrayOf(2, 0, 4)), + arrayOf(intArrayOf(0, 1), intArrayOf(2, 0), intArrayOf(1, 2)), + ), + equalTo(intArrayOf(1, 0, 2)), + ) + } + + @Test + fun findMedian3() { + assertThat( + Solution() + .findMedian( + 5, + arrayOf( + intArrayOf(0, 1, 2), + intArrayOf(0, 2, 5), + intArrayOf(1, 3, 1), + intArrayOf(2, 4, 3), + ), + arrayOf(intArrayOf(3, 4), intArrayOf(1, 2)), + ), + equalTo(intArrayOf(2, 2)), + ) + } +} From ed7c7af3dee6d48ceda6bfef15de23df382d7aa2 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Mon, 16 Jun 2025 12:46:30 +0300 Subject: [PATCH 2/6] Updated tags --- .../Solution.kt | 2 +- .../s3583_count_special_triplets/Solution.kt | 20 +++++++++---------- .../Solution.kt | 2 +- .../Solution.kt | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt b/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt index 65d40a6d..a6e755b7 100644 --- a/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt @@ -1,6 +1,6 @@ package g3501_3600.s3582_generate_tag_for_video_caption -// #Easy #2025_06_16_Time_12_ms_(100.00%)_Space_45.47_MB_(100.00%) +// #Easy #2025_06_16_Time_40_ms_(100.00%)_Space_46.98_MB_(55.56%) import java.util.Locale diff --git a/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt b/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt index 217a36e3..8f0f55a6 100644 --- a/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt @@ -1,22 +1,22 @@ package g3501_3600.s3583_count_special_triplets -// #Medium #2025_06_16_Time_250_ms_(100.00%)_Space_62.22_MB_(100.00%) +// #Medium #2025_06_16_Time_263_ms_(100.00%)_Space_99.88_MB_(42.86%) class Solution { fun specialTriplets(nums: IntArray): Int { - val mod = 1000000007 + val mod = 1_000_000_007 var res = 0 - val left: MutableMap = HashMap() - val right: MutableMap = HashMap() + val left = mutableMapOf() + val right = mutableMapOf() for (num in nums) { - right.put(num, right.getOrDefault(num, 0) + 1) + right[num] = right.getOrDefault(num, 0) + 1 } for (num in nums) { - right.put(num, right[num]!! - 1) - val ci: Int = left.getOrDefault(num * 2, 0) - val ck: Int = right.getOrDefault(num * 2, 0) - res = (res + ci * ck) % mod - left.put(num, left.getOrDefault(num, 0) + 1) + right[num] = right[num]!! - 1 + val ci = left.getOrDefault(num * 2, 0) + val ck = right.getOrDefault(num * 2, 0) + res = ((res + 1L * ci * ck) % mod).toInt() + left[num] = left.getOrDefault(num, 0) + 1 } return res } diff --git a/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt b/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt index 126b7eea..db3787b5 100644 --- a/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt @@ -1,6 +1,6 @@ package g3501_3600.s3584_maximum_product_of_first_and_last_elements_of_a_subsequence -// #Medium #2025_06_16_Time_4_ms_(87.17%)_Space_61.31_MB_(100.00%) +// #Medium #2025_06_16_Time_8_ms_(100.00%)_Space_72.69_MB_(100.00%) import kotlin.math.max import kotlin.math.min diff --git a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt index f7d9fffa..9afa2ffb 100644 --- a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt @@ -1,6 +1,6 @@ package g3501_3600.s3585_find_weighted_median_node_in_tree -// #Hard #2025_06_16_Time_162_ms_(100.00%)_Space_141.58_MB_(100.00%) +// #Hard #2025_06_16_Time_169_ms_(100.00%)_Space_171.76_MB_(100.00%) class Solution { private var log = 0 From 5cc85c5b42a420033f4b0a3c3f2a5c4138d3cc48 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 17 Jun 2025 08:10:54 +0300 Subject: [PATCH 3/6] Updated tags --- .../Solution.kt | 57 +++--- .../s3583_count_special_triplets/Solution.kt | 2 +- .../Solution.kt | 2 +- .../Solution.kt | 193 ++++++++++-------- 4 files changed, 137 insertions(+), 117 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt b/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt index a6e755b7..871633ea 100644 --- a/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt @@ -1,38 +1,39 @@ package g3501_3600.s3582_generate_tag_for_video_caption -// #Easy #2025_06_16_Time_40_ms_(100.00%)_Space_46.98_MB_(55.56%) - -import java.util.Locale +// #Easy #String #Simulation #2025_06_17_Time_3_ms_(100.00%)_Space_45.13_MB_(85.00%) class Solution { fun generateTag(caption: String): String? { - if (caption.trim { it <= ' ' }.isEmpty()) { - return "#" - } - val arr = caption.trim { it <= ' ' }.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - val res = StringBuilder("#") - var firstWord = arr[0] - firstWord = - ( - firstWord.substring(0, 1).lowercase(Locale.getDefault()) + - (if (firstWord.length > 1) firstWord.substring(1).lowercase(Locale.getDefault()) else "") - ) - res.append(firstWord) - for (i in 1.. 1) w.substring(1).lowercase(Locale.getDefault()) else "") - ) - res.append(w) - if (res.length >= 100) { - break + if (c >= 'A' && c <= 'Z') { + if (space) { + space = !space + sb.append(c) + } else { + sb.append(c.lowercaseChar()) + } } + if (c >= 'a' && c <= 'z') { + if (space) { + space = !space + sb.append(c.uppercaseChar()) + } else { + sb.append(c) + } + } + } + if (sb.length > 100) { + return sb.substring(0, 100) } - return if (res.length > 100) res.substring(0, 100) else res.toString() + return sb.toString() } } diff --git a/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt b/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt index 8f0f55a6..6339eb08 100644 --- a/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3583_count_special_triplets/Solution.kt @@ -1,6 +1,6 @@ package g3501_3600.s3583_count_special_triplets -// #Medium #2025_06_16_Time_263_ms_(100.00%)_Space_99.88_MB_(42.86%) +// #Medium #Array #Hash_Table #Counting #2025_06_17_Time_238_ms_(55.56%)_Space_83.48_MB_(77.78%) class Solution { fun specialTriplets(nums: IntArray): Int { diff --git a/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt b/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt index db3787b5..ec3efa8e 100644 --- a/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3584_maximum_product_of_first_and_last_elements_of_a_subsequence/Solution.kt @@ -1,6 +1,6 @@ package g3501_3600.s3584_maximum_product_of_first_and_last_elements_of_a_subsequence -// #Medium #2025_06_16_Time_8_ms_(100.00%)_Space_72.69_MB_(100.00%) +// #Medium #Array #Two_Pointers #2025_06_17_Time_8_ms_(100.00%)_Space_80.95_MB_(50.00%) import kotlin.math.max import kotlin.math.min diff --git a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt index 9afa2ffb..707dc76d 100644 --- a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt @@ -1,122 +1,141 @@ package g3501_3600.s3585_find_weighted_median_node_in_tree -// #Hard #2025_06_16_Time_169_ms_(100.00%)_Space_171.76_MB_(100.00%) +// #Hard #Array #Dynamic_Programming #Tree #Binary_Search #Depth_First_Search +// #2025_06_17_Time_123_ms_(100.00%)_Space_184.68_MB_(100.00%) + +import kotlin.math.ceil +import kotlin.math.ln class Solution { - private var log = 0 - private lateinit var dist: LongArray + private lateinit var adj: MutableList> private lateinit var depth: IntArray - private lateinit var up: Array + private lateinit var dist: LongArray + private lateinit var parent: Array + private var longMax = 0 + private var nodes = 0 fun findMedian(n: Int, edges: Array, queries: Array): IntArray { - val adj: MutableList?> = ArrayList?>() + nodes = n + if (n > 1) { + longMax = ceil(ln(n.toDouble()) / ln(2.0)).toInt() + } else { + longMax = 1 + } + adj = ArrayList>() for (i in 0..()) } for (edge in edges) { - adj[edge[0]]!!.add(intArrayOf(edge[1], edge[2])) - adj[edge[1]]!!.add(intArrayOf(edge[0], edge[2])) + val u = edge[0] + val v = edge[1] + val w = edge[2] + adj[u].add(intArrayOf(v, w)) + adj[v].add(intArrayOf(u, w)) } - dist = LongArray(n) depth = IntArray(n) - log = 0 - while (1 shl log < n) { - log++ - } - up = Array(n) { IntArray(log) } - for (u in up) { - u.fill(-1) + dist = LongArray(n) + parent = Array(longMax) { IntArray(n) } + for (i in 0..= needed - ) { - continue - } - curDistance += getDistance(up[first][j], first) - first = up[first][j] - } - ans[i] = up[first][0] - } + var sabrelonta: IntArray + for (qIdx in queries.indices) { + sabrelonta = queries[qIdx] + val u = sabrelonta[0] + val v = sabrelonta[1] + ans[qIdx] = findMedianNode(u, v) } + return ans } - private fun getDistance(from: Int, to: Int): Long { - if (from == to) { - return 0 + private fun dfs(u: Int, p: Int, d: Int, currentDist: Long) { + depth[u] = d + parent[0][u] = p + dist[u] = currentDist + for (edge in adj[u]) { + val v = edge[0] + val w = edge[1] + if (v == p) { + continue + } + dfs(v, u, d + 1, currentDist + w) } - val ancesor = lca(from, to) - return dist[from] + dist[to] - 2 * dist[ancesor] } - private fun lca(first: Int, second: Int): Int { - var first = first - var second = second - if (depth[first] < depth[second]) { - return lca(second, first) + private fun buildLcaTable() { + for (k in 1..= depth[second]) { - first = up[first][i] + } + + private fun getKthAncestor(u: Int, k: Int): Int { + var u = u + for (p in longMax - 1 downTo 0) { + if (u == -1) { + break + } + if (((k shr p) and 1) == 1) { + u = parent[p][u] } } - if (first == second) { - return second + return u + } + + private fun getLCA(u: Int, v: Int): Int { + var u = u + var v = v + if (depth[u] < depth[v]) { + val temp = u + u = v + v = temp } - for (i in log - 1 downTo 0) { - if (depth[first] != -1 && up[first][i] != up[second][i]) { - first = up[first][i] - second = up[second][i] + u = getKthAncestor(u, depth[u] - depth[v]) + if (u == v) { + return u + } + for (p in longMax - 1 downTo 0) { + if (parent[p][u] != -1 && parent[p][u] != parent[p][v]) { + u = parent[p][u] + v = parent[p][v] } } - first = up[first][0] - return first + return parent[0][u] } - private fun dfs(current: Int, parent: Int, adj: MutableList?>, curDist: Long, curDepth: Int) { - up[current][0] = parent - for (i in 1..= halfWeight) { + var curr = u + for (p in longMax - 1 downTo 0) { + val nextNode = parent[p][curr] + if (nextNode != -1 && (dist[u] - dist[nextNode] < halfWeight)) { + curr = nextNode + } + } + return parent[0][curr] + } else { + val remainingWeightFromLCA = halfWeight - (dist[u] - dist[lca]) + var curr = v + for (p in longMax - 1 downTo 0) { + val nextNode = parent[p][curr] + if (nextNode != -1 && depth[nextNode] >= depth[lca] && (dist[nextNode] - dist[lca]) >= remainingWeightFromLCA) { + curr = nextNode + } } - dfs(next[0], current, adj, curDist + next[1], curDepth + 1) + return curr } } } From 472fb0c5f8d75d72ee8170878285415ce0ad1549 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 17 Jun 2025 08:14:26 +0300 Subject: [PATCH 4/6] Fixed style --- .../s3585_find_weighted_median_node_in_tree/Solution.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt index 707dc76d..b9376d2a 100644 --- a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt @@ -131,7 +131,9 @@ class Solution { var curr = v for (p in longMax - 1 downTo 0) { val nextNode = parent[p][curr] - if (nextNode != -1 && depth[nextNode] >= depth[lca] && (dist[nextNode] - dist[lca]) >= remainingWeightFromLCA) { + if (nextNode != -1 && depth[nextNode] >= depth[lca] && + (dist[nextNode] - dist[lca]) >= remainingWeightFromLCA + ) { curr = nextNode } } From 0f82033d3e54dea37ecf9f35eb195927698976b7 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 17 Jun 2025 08:21:52 +0300 Subject: [PATCH 5/6] Updated gradle settings --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d0ccec97..732fad51 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ sonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml -org.gradle.jvmargs=-Xms256m -Xmx1024m +org.gradle.jvmargs=-Xms512m -Xmx2048m From 49b78915872ad7b18d1f3e2187fc85f8c5d6e676 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 17 Jun 2025 08:24:52 +0300 Subject: [PATCH 6/6] Fixed sonar --- .../Solution.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt index b9376d2a..53ec98dc 100644 --- a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt +++ b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt @@ -21,9 +21,9 @@ class Solution { } else { longMax = 1 } - adj = ArrayList>() + adj = ArrayList() for (i in 0..()) + adj.add(ArrayList()) } for (edge in edges) { val u = edge[0] @@ -34,7 +34,7 @@ class Solution { } depth = IntArray(n) dist = LongArray(n) - parent = Array(longMax) { IntArray(n) } + parent = Array(longMax) { IntArray(n) } for (i in 0..= halfWeight) { + return if (dist[u] - dist[lca] >= halfWeight) { var curr = u for (p in longMax - 1 downTo 0) { val nextNode = parent[p][curr] @@ -125,7 +125,7 @@ class Solution { curr = nextNode } } - return parent[0][curr] + parent[0][curr] } else { val remainingWeightFromLCA = halfWeight - (dist[u] - dist[lca]) var curr = v @@ -137,7 +137,7 @@ class Solution { curr = nextNode } } - return curr + curr } } }