diff --git a/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/Solution.kt b/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/Solution.kt new file mode 100644 index 000000000..9c4b33e22 --- /dev/null +++ b/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/Solution.kt @@ -0,0 +1,27 @@ +package g3201_3300.s3248_snake_in_matrix + +// #Easy #Array #String #Simulation #2024_08_13_Time_174_ms_(90.91%)_Space_37.5_MB_(34.09%) + +class Solution { + fun finalPositionOfSnake(n: Int, commands: List): Int { + var x = 0 + var y = 0 + for (command in commands) { + when (command) { + "UP" -> if (x > 0) { + x-- + } + "DOWN" -> if (x < n - 1) { + x++ + } + "LEFT" -> if (y > 0) { + y-- + } + "RIGHT" -> if (y < n - 1) { + y++ + } + } + } + return (x * n) + y + } +} diff --git a/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/image01.png b/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/image01.png new file mode 100644 index 000000000..d32550a78 Binary files /dev/null and b/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/image01.png differ diff --git a/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/image02.png b/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/image02.png new file mode 100644 index 000000000..00305b026 Binary files /dev/null and b/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/image02.png differ diff --git a/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/readme.md b/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/readme.md new file mode 100644 index 000000000..71498b4af --- /dev/null +++ b/src/main/kotlin/g3201_3300/s3248_snake_in_matrix/readme.md @@ -0,0 +1,38 @@ +3248\. Snake in Matrix + +Easy + +There is a snake in an `n x n` matrix `grid` and can move in **four possible directions**. Each cell in the `grid` is identified by the position: `grid[i][j] = (i * n) + j`. + +The snake starts at cell 0 and follows a sequence of commands. + +You are given an integer `n` representing the size of the `grid` and an array of strings `commands` where each `command[i]` is either `"UP"`, `"RIGHT"`, `"DOWN"`, and `"LEFT"`. It's guaranteed that the snake will remain within the `grid` boundaries throughout its movement. + +Return the position of the final cell where the snake ends up after executing `commands`. + +**Example 1:** + +**Input:** n = 2, commands = ["RIGHT","DOWN"] + +**Output:** 3 + +**Explanation:** + +![image](image01.png) + +**Example 2:** + +**Input:** n = 3, commands = ["DOWN","RIGHT","UP"] + +**Output:** 1 + +**Explanation:** + +![image](image02.png) + +**Constraints:** + +* `2 <= n <= 10` +* `1 <= commands.length <= 100` +* `commands` consists only of `"UP"`, `"RIGHT"`, `"DOWN"`, and `"LEFT"`. +* The input is generated such the snake will not move outside of the boundaries. \ No newline at end of file diff --git a/src/main/kotlin/g3201_3300/s3249_count_the_number_of_good_nodes/Solution.kt b/src/main/kotlin/g3201_3300/s3249_count_the_number_of_good_nodes/Solution.kt new file mode 100644 index 000000000..1fd59e240 --- /dev/null +++ b/src/main/kotlin/g3201_3300/s3249_count_the_number_of_good_nodes/Solution.kt @@ -0,0 +1,64 @@ +package g3201_3300.s3249_count_the_number_of_good_nodes + +// #Medium #Depth_First_Search #Tree #2024_08_13_Time_1190_ms_(100.00%)_Space_127.6_MB_(77.27%) + +class Solution { + private var count = 0 + + fun countGoodNodes(edges: Array): Int { + val n = edges.size + 1 + val nodes = arrayOfNulls(n) + nodes[0] = TNode() + for (edge in edges) { + val a = edge[0] + val b = edge[1] + if (nodes[b] != null && nodes[a] == null) { + nodes[a] = TNode() + nodes[b]!!.children.add(nodes[a]) + } else { + if (nodes[a] == null) { + nodes[a] = TNode() + } + if (nodes[b] == null) { + nodes[b] = TNode() + } + nodes[a]!!.children.add(nodes[b]) + } + } + sizeOfTree(nodes[0]) + return count + } + + private fun sizeOfTree(node: TNode?): Int { + if (node!!.size > 0) { + return node.size + } + val children: List = node.children + if (children.isEmpty()) { + count++ + node.size = 1 + return 1 + } + val size = sizeOfTree(children[0]) + var sum = size + var goodNode = true + for (i in 1 until children.size) { + val child = children[i] + if (size != sizeOfTree(child)) { + goodNode = false + } + sum += sizeOfTree(child) + } + if (goodNode) { + count++ + } + sum++ + node.size = sum + return sum + } + + private class TNode { + var size: Int = -1 + var children: MutableList = ArrayList() + } +} diff --git a/src/main/kotlin/g3201_3300/s3249_count_the_number_of_good_nodes/readme.md b/src/main/kotlin/g3201_3300/s3249_count_the_number_of_good_nodes/readme.md new file mode 100644 index 000000000..f406a5b7f --- /dev/null +++ b/src/main/kotlin/g3201_3300/s3249_count_the_number_of_good_nodes/readme.md @@ -0,0 +1,55 @@ +3249\. Count the Number of Good Nodes + +Medium + +There is an **undirected** tree with `n` nodes labeled from `0` to `n - 1`, and rooted at node `0`. You are given a 2D integer array `edges` of length `n - 1`, where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the tree. + +A node is **good** if all the subtrees rooted at its children have the same size. + +Return the number of **good** nodes in the given tree. + +A **subtree** of `treeName` is a tree consisting of a node in `treeName` and all of its descendants. + +**Example 1:** + +**Input:** edges = [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6]] + +**Output:** 7 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2024/05/26/tree1.png) + +All of the nodes of the given tree are good. + +**Example 2:** + +**Input:** edges = [[0,1],[1,2],[2,3],[3,4],[0,5],[1,6],[2,7],[3,8]] + +**Output:** 6 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2024/06/03/screenshot-2024-06-03-193552.png) + +There are 6 good nodes in the given tree. They are colored in the image above. + +**Example 3:** + +**Input:** edges = [[0,1],[1,2],[1,3],[1,4],[0,5],[5,6],[6,7],[7,8],[0,9],[9,10],[9,12],[10,11]] + +**Output:** 12 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2024/08/08/rob.jpg) + +All nodes except node 9 are good. + +**Constraints:** + +* 2 <= n <= 105 +* `edges.length == n - 1` +* `edges[i].length == 2` +* 0 <= ai, bi < n +* The input is generated such that `edges` represents a valid tree. \ No newline at end of file diff --git a/src/main/kotlin/g3201_3300/s3250_find_the_count_of_monotonic_pairs_i/Solution.kt b/src/main/kotlin/g3201_3300/s3250_find_the_count_of_monotonic_pairs_i/Solution.kt new file mode 100644 index 000000000..3f31268ec --- /dev/null +++ b/src/main/kotlin/g3201_3300/s3250_find_the_count_of_monotonic_pairs_i/Solution.kt @@ -0,0 +1,46 @@ +package g3201_3300.s3250_find_the_count_of_monotonic_pairs_i + +// #Hard #Array #Dynamic_Programming #Math #Prefix_Sum #Combinatorics +// #2024_08_13_Time_241_ms_(100.00%)_Space_39.2_MB_(100.00%) + +import kotlin.math.max +import kotlin.math.min + +class Solution { + fun countOfPairs(nums: IntArray): Int { + val maxShift = IntArray(nums.size) + maxShift[0] = nums[0] + var currShift = 0 + for (i in 1 until nums.size) { + currShift = max(currShift, (nums[i] - maxShift[i - 1])) + maxShift[i] = min(maxShift[i - 1], (nums[i] - currShift)) + if (maxShift[i] < 0) { + return 0 + } + } + val cases = getAllCases(nums, maxShift) + return cases[nums.size - 1]!![maxShift[nums.size - 1]] + } + + private fun getAllCases(nums: IntArray, maxShift: IntArray): Array { + var currCases: IntArray + val cases = arrayOfNulls(nums.size) + cases[0] = IntArray(maxShift[0] + 1) + for (i in cases[0]!!.indices) { + cases[0]!![i] = i + 1 + } + for (i in 1 until nums.size) { + currCases = IntArray(maxShift[i] + 1) + currCases[0] = 1 + for (j in 1 until currCases.size) { + val prevCases = + if (j < cases[i - 1]!!.size + ) cases[i - 1]!![j] + else cases[i - 1]!![cases[i - 1]!!.size - 1] + currCases[j] = (currCases[j - 1] + prevCases) % (1000000000 + 7) + } + cases[i] = currCases + } + return cases + } +} diff --git a/src/main/kotlin/g3201_3300/s3250_find_the_count_of_monotonic_pairs_i/readme.md b/src/main/kotlin/g3201_3300/s3250_find_the_count_of_monotonic_pairs_i/readme.md new file mode 100644 index 000000000..bab38cc45 --- /dev/null +++ b/src/main/kotlin/g3201_3300/s3250_find_the_count_of_monotonic_pairs_i/readme.md @@ -0,0 +1,42 @@ +3250\. Find the Count of Monotonic Pairs I + +Hard + +You are given an array of **positive** integers `nums` of length `n`. + +We call a pair of **non-negative** integer arrays `(arr1, arr2)` **monotonic** if: + +* The lengths of both arrays are `n`. +* `arr1` is monotonically **non-decreasing**, in other words, `arr1[0] <= arr1[1] <= ... <= arr1[n - 1]`. +* `arr2` is monotonically **non-increasing**, in other words, `arr2[0] >= arr2[1] >= ... >= arr2[n - 1]`. +* `arr1[i] + arr2[i] == nums[i]` for all `0 <= i <= n - 1`. + +Return the count of **monotonic** pairs. + +Since the answer may be very large, return it **modulo** 109 + 7. + +**Example 1:** + +**Input:** nums = [2,3,2] + +**Output:** 4 + +**Explanation:** + +The good pairs are: + +1. `([0, 1, 1], [2, 2, 1])` +2. `([0, 1, 2], [2, 2, 0])` +3. `([0, 2, 2], [2, 1, 0])` +4. `([1, 2, 2], [1, 1, 0])` + +**Example 2:** + +**Input:** nums = [5,5,5,5] + +**Output:** 126 + +**Constraints:** + +* `1 <= n == nums.length <= 2000` +* `1 <= nums[i] <= 50` \ No newline at end of file diff --git a/src/main/kotlin/g3201_3300/s3251_find_the_count_of_monotonic_pairs_ii/Solution.kt b/src/main/kotlin/g3201_3300/s3251_find_the_count_of_monotonic_pairs_ii/Solution.kt new file mode 100644 index 000000000..ffede479a --- /dev/null +++ b/src/main/kotlin/g3201_3300/s3251_find_the_count_of_monotonic_pairs_ii/Solution.kt @@ -0,0 +1,36 @@ +package g3201_3300.s3251_find_the_count_of_monotonic_pairs_ii + +// #Hard #Array #Dynamic_Programming #Math #Prefix_Sum #Combinatorics +// #2024_08_13_Time_291_ms_(100.00%)_Space_47_MB_(100.00%) + +import kotlin.math.max + +class Solution { + fun countOfPairs(nums: IntArray): Int { + var prefixZeros = 0 + val n = nums.size + // Calculate prefix zeros + for (i in 1 until n) { + prefixZeros += max((nums[i] - nums[i - 1]), 0) + } + val row = n + 1 + val col = nums[n - 1] + 1 - prefixZeros + if (col <= 0) { + return 0 + } + // Initialize dp array + val dp = IntArray(col) + dp.fill(1) + // Fill dp array + for (r in 1 until row) { + for (c in 1 until col) { + dp[c] = (dp[c] + dp[c - 1]) % MOD + } + } + return dp[col - 1] + } + + companion object { + private const val MOD = 1000000007 + } +} diff --git a/src/main/kotlin/g3201_3300/s3251_find_the_count_of_monotonic_pairs_ii/readme.md b/src/main/kotlin/g3201_3300/s3251_find_the_count_of_monotonic_pairs_ii/readme.md new file mode 100644 index 000000000..171b2dfbf --- /dev/null +++ b/src/main/kotlin/g3201_3300/s3251_find_the_count_of_monotonic_pairs_ii/readme.md @@ -0,0 +1,42 @@ +3251\. Find the Count of Monotonic Pairs II + +Hard + +You are given an array of **positive** integers `nums` of length `n`. + +We call a pair of **non-negative** integer arrays `(arr1, arr2)` **monotonic** if: + +* The lengths of both arrays are `n`. +* `arr1` is monotonically **non-decreasing**, in other words, `arr1[0] <= arr1[1] <= ... <= arr1[n - 1]`. +* `arr2` is monotonically **non-increasing**, in other words, `arr2[0] >= arr2[1] >= ... >= arr2[n - 1]`. +* `arr1[i] + arr2[i] == nums[i]` for all `0 <= i <= n - 1`. + +Return the count of **monotonic** pairs. + +Since the answer may be very large, return it **modulo** 109 + 7. + +**Example 1:** + +**Input:** nums = [2,3,2] + +**Output:** 4 + +**Explanation:** + +The good pairs are: + +1. `([0, 1, 1], [2, 2, 1])` +2. `([0, 1, 2], [2, 2, 0])` +3. `([0, 2, 2], [2, 1, 0])` +4. `([1, 2, 2], [1, 1, 0])` + +**Example 2:** + +**Input:** nums = [5,5,5,5] + +**Output:** 126 + +**Constraints:** + +* `1 <= n == nums.length <= 2000` +* `1 <= nums[i] <= 1000` \ No newline at end of file diff --git a/src/test/kotlin/g3201_3300/s3248_snake_in_matrix/SolutionTest.kt b/src/test/kotlin/g3201_3300/s3248_snake_in_matrix/SolutionTest.kt new file mode 100644 index 000000000..3523313d4 --- /dev/null +++ b/src/test/kotlin/g3201_3300/s3248_snake_in_matrix/SolutionTest.kt @@ -0,0 +1,76 @@ +package g3201_3300.s3248_snake_in_matrix + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun finalPositionOfSnake() { + assertThat(Solution().finalPositionOfSnake(2, listOf("RIGHT", "DOWN")), equalTo(3)) + } + + @Test + fun finalPositionOfSnake2() { + assertThat( + Solution().finalPositionOfSnake(3, listOf("DOWN", "RIGHT", "UP")), equalTo(1) + ) + } + + @Test + fun testFinalPositionOfSnakeAllCommands() { + val commands: List = listOf("UP", "DOWN", "LEFT", "RIGHT") + val result = Solution().finalPositionOfSnake(3, commands) + assertEquals(4, result) + } + + @Test + fun testFinalPositionOfSnakeOnlyUp() { + val commands: List = listOf("UP", "UP") + val result = Solution().finalPositionOfSnake(3, commands) + assertEquals(0, result) + } + + @Test + fun testFinalPositionOfSnakeOnlyDown() { + val commands: List = listOf("DOWN", "DOWN") + val result = Solution().finalPositionOfSnake(3, commands) + assertEquals(6, result) + } + + @Test + fun testFinalPositionOfSnakeOnlyLeft() { + val commands: List = listOf("LEFT", "LEFT") + val result = Solution().finalPositionOfSnake(3, commands) + assertEquals(0, result) + } + + @Test + fun testFinalPositionOfSnakeOnlyRight() { + val commands: List = listOf("RIGHT", "RIGHT") + val result = Solution().finalPositionOfSnake(3, commands) + assertEquals(2, result) + } + + @Test + fun testFinalPositionOfSnakeEmptyCommands() { + val commands: List = listOf() + val result = Solution().finalPositionOfSnake(3, commands) + assertEquals(0, result) + } + + @Test + fun testFinalPositionOfSnakeMixedCommands() { + val commands: List = listOf("DOWN", "RIGHT", "UP", "LEFT", "UP", "DOWN", "RIGHT") + val result = Solution().finalPositionOfSnake(3, commands) + assertEquals(4, result) + } + + @Test + fun testFinalPositionOfSnakeInvalidCommands() { + val commands: List = listOf("DOWN", "RIGHT", "JUMP", "LEFT", "UP", "DOWN", "RIGHT") + val result = Solution().finalPositionOfSnake(3, commands) + assertEquals(4, result) + } +} diff --git a/src/test/kotlin/g3201_3300/s3249_count_the_number_of_good_nodes/SolutionTest.kt b/src/test/kotlin/g3201_3300/s3249_count_the_number_of_good_nodes/SolutionTest.kt new file mode 100644 index 000000000..c035a7bf9 --- /dev/null +++ b/src/test/kotlin/g3201_3300/s3249_count_the_number_of_good_nodes/SolutionTest.kt @@ -0,0 +1,45 @@ +package g3201_3300.s3249_count_the_number_of_good_nodes + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun countGoodNodes() { + assertThat( + Solution() + .countGoodNodes( + arrayOf( + intArrayOf(0, 1), + intArrayOf(0, 2), + intArrayOf(1, 3), + intArrayOf(1, 4), + intArrayOf(2, 5), + intArrayOf(2, 6) + ) + ), + equalTo(7) + ) + } + + @Test + fun countGoodNodes2() { + assertThat( + Solution() + .countGoodNodes( + arrayOf( + intArrayOf(0, 1), + intArrayOf(1, 2), + intArrayOf(2, 3), + intArrayOf(3, 4), + intArrayOf(0, 5), + intArrayOf(1, 6), + intArrayOf(2, 7), + intArrayOf(3, 8) + ) + ), + equalTo(6) + ) + } +} diff --git a/src/test/kotlin/g3201_3300/s3250_find_the_count_of_monotonic_pairs_i/SolutionTest.kt b/src/test/kotlin/g3201_3300/s3250_find_the_count_of_monotonic_pairs_i/SolutionTest.kt new file mode 100644 index 000000000..a6a279238 --- /dev/null +++ b/src/test/kotlin/g3201_3300/s3250_find_the_count_of_monotonic_pairs_i/SolutionTest.kt @@ -0,0 +1,17 @@ +package g3201_3300.s3250_find_the_count_of_monotonic_pairs_i + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun countOfPairs() { + assertThat(Solution().countOfPairs(intArrayOf(2, 3, 2)), equalTo(4)) + } + + @Test + fun countOfPairs2() { + assertThat(Solution().countOfPairs(intArrayOf(5, 5, 5, 5)), equalTo(126)) + } +} diff --git a/src/test/kotlin/g3201_3300/s3251_find_the_count_of_monotonic_pairs_ii/SolutionTest.kt b/src/test/kotlin/g3201_3300/s3251_find_the_count_of_monotonic_pairs_ii/SolutionTest.kt new file mode 100644 index 000000000..946951a7a --- /dev/null +++ b/src/test/kotlin/g3201_3300/s3251_find_the_count_of_monotonic_pairs_ii/SolutionTest.kt @@ -0,0 +1,17 @@ +package g3201_3300.s3251_find_the_count_of_monotonic_pairs_ii + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun countOfPairs() { + assertThat(Solution().countOfPairs(intArrayOf(2, 3, 2)), equalTo(4)) + } + + @Test + fun countOfPairs2() { + assertThat(Solution().countOfPairs(intArrayOf(5, 5, 5, 5)), equalTo(126)) + } +}