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 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..871633ea --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3582_generate_tag_for_video_caption/Solution.kt @@ -0,0 +1,39 @@ +package g3501_3600.s3582_generate_tag_for_video_caption + +// #Easy #String #Simulation #2025_06_17_Time_3_ms_(100.00%)_Space_45.13_MB_(85.00%) + +class Solution { + fun generateTag(caption: String): String? { + var caption = caption + val sb = StringBuilder() + sb.append('#') + var space = false + caption = caption.trim { it <= ' ' } + for (i in 0..= '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 sb.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..6339eb08 --- /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 #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 { + val mod = 1_000_000_007 + var res = 0 + val left = mutableMapOf() + val right = mutableMapOf() + for (num in nums) { + right[num] = right.getOrDefault(num, 0) + 1 + } + for (num in nums) { + 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/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..ec3efa8e --- /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 #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 + +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..53ec98dc --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/Solution.kt @@ -0,0 +1,143 @@ +package g3501_3600.s3585_find_weighted_median_node_in_tree + +// #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 lateinit var adj: MutableList> + private lateinit var depth: IntArray + 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 { + nodes = n + if (n > 1) { + longMax = ceil(ln(n.toDouble()) / ln(2.0)).toInt() + } else { + longMax = 1 + } + adj = ArrayList() + for (i in 0..= 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 + } + } + 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 + } + } + curr + } + } +} diff --git a/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/readme.md b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/readme.md new file mode 100644 index 00000000..69a344aa --- /dev/null +++ b/src/main/kotlin/g3501_3600/s3585_find_weighted_median_node_in_tree/readme.md @@ -0,0 +1,70 @@ +3585\. Find Weighted Median Node in Tree + +Hard + +You are given an integer `n` and an **undirected, weighted** tree rooted at node 0 with `n` nodes numbered from 0 to `n - 1`. This is represented by a 2D array `edges` of length `n - 1`, where 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)), + ) + } +}