From 0aa000992fe5941b6138a123c7ae0dd3ea6e982c Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Thu, 16 Mar 2023 08:29:33 +0200 Subject: [PATCH] Added tasks 797-805 --- README.md | 11 ++ .../g0401_0500/s0493_reverse_pairs/readme.md | 4 +- .../readme.md | 4 +- .../readme.md | 64 +++++++++ .../readme.md | 69 +++++++++ .../s0799_champagne_tower/readme.md | 80 +++++++++++ .../readme.md | 60 ++++++++ .../s0802_find_eventual_safe_states/readme.md | 71 ++++++++++ .../s0803_bricks_falling_when_hit/readme.md | 133 ++++++++++++++++++ .../s0804_unique_morse_code_words/readme.md | 75 ++++++++++ .../readme.md | 85 +++++++++++ 11 files changed, 650 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/g0701_0800/s0797_all_paths_from_source_to_target/readme.md create mode 100644 src/main/kotlin/g0701_0800/s0798_smallest_rotation_with_highest_score/readme.md create mode 100644 src/main/kotlin/g0701_0800/s0799_champagne_tower/readme.md create mode 100644 src/main/kotlin/g0801_0900/s0801_minimum_swaps_to_make_sequences_increasing/readme.md create mode 100644 src/main/kotlin/g0801_0900/s0802_find_eventual_safe_states/readme.md create mode 100644 src/main/kotlin/g0801_0900/s0803_bricks_falling_when_hit/readme.md create mode 100644 src/main/kotlin/g0801_0900/s0804_unique_morse_code_words/readme.md create mode 100644 src/main/kotlin/g0801_0900/s0805_split_array_with_same_average/readme.md diff --git a/README.md b/README.md index f4d49a1d..53606439 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ | | | | | | |-|-|-|-|-|- +| 0797 |[All Paths From Source to Target](src/main/kotlin/g0701_0800/s0797_all_paths_from_source_to_target)| Medium | Depth_First_Search, Breadth_First_Search, Graph, Backtracking | 232 | 100.00 #### Day 8 Standard Traversal @@ -69,6 +70,7 @@ | | | | | | |-|-|-|-|-|- +| 0802 |[Find Eventual Safe States](src/main/kotlin/g0801_0900/s0802_find_eventual_safe_states)| Medium | Depth_First_Search, Breadth_First_Search, Graph, Topological_Sort | 511 | 100.00 #### Day 10 Standard Traversal @@ -1028,6 +1030,7 @@ | | | | | | |-|-|-|-|-|- | 0130 |[Surrounded Regions](src/main/kotlin/g0101_0200/s0130_surrounded_regions)| Medium | Top_Interview_Questions, Array, Depth_First_Search, Breadth_First_Search, Matrix, Union_Find | 355 | 84.42 +| 0797 |[All Paths From Source to Target](src/main/kotlin/g0701_0800/s0797_all_paths_from_source_to_target)| Medium | Depth_First_Search, Breadth_First_Search, Graph, Backtracking | 232 | 100.00 #### Day 9 Recursion Backtracking @@ -1676,6 +1679,14 @@ | 1143 |[Longest Common Subsequence](src/main/kotlin/g1101_1200/s1143_longest_common_subsequence)| Medium | Top_100_Liked_Questions, String, Dynamic_Programming, Algorithm_II_Day_17_Dynamic_Programming, Dynamic_Programming_I_Day_19, Udemy_Dynamic_Programming | 307 | 38.36 | 0994 |[Rotting Oranges](src/main/kotlin/g0901_1000/s0994_rotting_oranges)| Medium | Array, Breadth_First_Search, Matrix, Algorithm_I_Day_9_Breadth_First_Search_Depth_First_Search, Level_2_Day_10_Graph/BFS/DFS | 308 | 57.93 | 0864 |[Shortest Path to Get All Keys](src/main/kotlin/g0801_0900/s0864_shortest_path_to_get_all_keys)| Hard | Breadth_First_Search, Bit_Manipulation | 176 | 100.00 +| 0805 |[Split Array With Same Average](src/main/kotlin/g0801_0900/s0805_split_array_with_same_average)| Hard | Array, Dynamic_Programming, Math, Bit_Manipulation, Bitmask | 142 | 100.00 +| 0804 |[Unique Morse Code Words](src/main/kotlin/g0801_0900/s0804_unique_morse_code_words)| Easy | Array, String, Hash_Table | 158 | 80.00 +| 0803 |[Bricks Falling When Hit](src/main/kotlin/g0801_0900/s0803_bricks_falling_when_hit)| Hard | Array, Matrix, Union_Find | 742 | 100.00 +| 0802 |[Find Eventual Safe States](src/main/kotlin/g0801_0900/s0802_find_eventual_safe_states)| Medium | Depth_First_Search, Breadth_First_Search, Graph, Topological_Sort, Graph_Theory_I_Day_9_Standard_Traversal | 511 | 100.00 +| 0801 |[Minimum Swaps To Make Sequences Increasing](src/main/kotlin/g0801_0900/s0801_minimum_swaps_to_make_sequences_increasing)| Hard | Array, Dynamic_Programming | 617 | 83.33 +| 0799 |[Champagne Tower](src/main/kotlin/g0701_0800/s0799_champagne_tower)| Medium | Dynamic_Programming | 153 | 100.00 +| 0798 |[Smallest Rotation with Highest Score](src/main/kotlin/g0701_0800/s0798_smallest_rotation_with_highest_score)| Hard | Array, Prefix_Sum | 470 | 100.00 +| 0797 |[All Paths From Source to Target](src/main/kotlin/g0701_0800/s0797_all_paths_from_source_to_target)| Medium | Depth_First_Search, Breadth_First_Search, Graph, Backtracking, Algorithm_II_Day_8_Breadth_First_Search_Depth_First_Search, Graph_Theory_I_Day_7_Standard_Traversal | 232 | 100.00 | 0796 |[Rotate String](src/main/kotlin/g0701_0800/s0796_rotate_string)| Easy | String, String_Matching | 134 | 100.00 | 0795 |[Number of Subarrays with Bounded Maximum](src/main/kotlin/g0701_0800/s0795_number_of_subarrays_with_bounded_maximum)| Medium | Array, Two_Pointers | 361 | 66.67 | 0794 |[Valid Tic-Tac-Toe State](src/main/kotlin/g0701_0800/s0794_valid_tic_tac_toe_state)| Medium | Array, String | 138 | 100.00 diff --git a/src/main/kotlin/g0401_0500/s0493_reverse_pairs/readme.md b/src/main/kotlin/g0401_0500/s0493_reverse_pairs/readme.md index d41e2799..1ca1a52c 100644 --- a/src/main/kotlin/g0401_0500/s0493_reverse_pairs/readme.md +++ b/src/main/kotlin/g0401_0500/s0493_reverse_pairs/readme.md @@ -46,8 +46,6 @@ A **reverse pair** is a pair `(i, j)` where: ## Solution ```kotlin -import java.util.Arrays - class Solution { fun reversePairs(nums: IntArray): Int { return mergeSort(nums, 0, nums.size - 1) @@ -68,7 +66,7 @@ class Solution { } cnt += j - (mid + 1) } - Arrays.sort(nums, start, end + 1) + nums.sort(start, end + 1) return cnt } } diff --git a/src/main/kotlin/g0701_0800/s0787_cheapest_flights_within_k_stops/readme.md b/src/main/kotlin/g0701_0800/s0787_cheapest_flights_within_k_stops/readme.md index 249d831c..c12a5ad7 100644 --- a/src/main/kotlin/g0701_0800/s0787_cheapest_flights_within_k_stops/readme.md +++ b/src/main/kotlin/g0701_0800/s0787_cheapest_flights_within_k_stops/readme.md @@ -68,15 +68,13 @@ The optimal path with no stops from city 0 to 2 is marked in red and has cost 50 ## Solution ```kotlin -import java.util.Arrays - class Solution { fun findCheapestPrice(n: Int, flights: Array, src: Int, dst: Int, k: Int): Int { // k + 2 becase there are total of k(intermediate stops) + 1(src) + 1(dst) // dp[i][j] = cost to reach j using atmost i edges from src val dp = Array(k + 2) { IntArray(n) } for (row in dp) { - Arrays.fill(row, Int.MAX_VALUE) + row.fill(Int.MAX_VALUE) } // cost to reach src is always 0 for (i in 0..k + 1) { diff --git a/src/main/kotlin/g0701_0800/s0797_all_paths_from_source_to_target/readme.md b/src/main/kotlin/g0701_0800/s0797_all_paths_from_source_to_target/readme.md new file mode 100644 index 00000000..0891ef45 --- /dev/null +++ b/src/main/kotlin/g0701_0800/s0797_all_paths_from_source_to_target/readme.md @@ -0,0 +1,64 @@ +[![](https://img.shields.io/github/stars/javadev/LeetCode-in-Kotlin?label=Stars&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin) +[![](https://img.shields.io/github/forks/javadev/LeetCode-in-Kotlin?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin/fork) + +## 797\. All Paths From Source to Target + +Medium + +Given a directed acyclic graph (**DAG**) of `n` nodes labeled from `0` to `n - 1`, find all possible paths from node `0` to node `n - 1` and return them in **any order**. + +The graph is given as follows: `graph[i]` is a list of all nodes you can visit from node `i` (i.e., there is a directed edge from node `i` to node `graph[i][j]`). + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2020/09/28/all_1.jpg) + +**Input:** graph = \[\[1,2],[3],[3],[]] + +**Output:** [[0,1,3],[0,2,3]] + +**Explanation:** There are two paths: 0 -> 1 -> 3 and 0 -> 2 -> 3. + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2020/09/28/all_2.jpg) + +**Input:** graph = \[\[4,3,1],[3,2,4],[3],[4],[]] + +**Output:** [[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]] + +**Constraints:** + +* `n == graph.length` +* `2 <= n <= 15` +* `0 <= graph[i][j] < n` +* `graph[i][j] != i` (i.e., there will be no self-loops). +* All the elements of `graph[i]` are **unique**. +* The input graph is **guaranteed** to be a **DAG**. + +## Solution + +```kotlin +class Solution { + private var res: MutableList>? = null + fun allPathsSourceTarget(graph: Array): List> { + res = ArrayList() + val temp: MutableList = ArrayList() + temp.add(0) + // perform DFS + solve(graph, temp, 0) + return res as ArrayList> + } + + private fun solve(graph: Array, temp: MutableList, lastNode: Int) { + if (lastNode == graph.size - 1) { + res!!.add(ArrayList(temp)) + } + for (link in graph[lastNode]) { + temp.add(link) + solve(graph, temp, link) + temp.removeAt(temp.size - 1) + } + } +} +``` \ No newline at end of file diff --git a/src/main/kotlin/g0701_0800/s0798_smallest_rotation_with_highest_score/readme.md b/src/main/kotlin/g0701_0800/s0798_smallest_rotation_with_highest_score/readme.md new file mode 100644 index 00000000..aec39be8 --- /dev/null +++ b/src/main/kotlin/g0701_0800/s0798_smallest_rotation_with_highest_score/readme.md @@ -0,0 +1,69 @@ +[![](https://img.shields.io/github/stars/javadev/LeetCode-in-Kotlin?label=Stars&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin) +[![](https://img.shields.io/github/forks/javadev/LeetCode-in-Kotlin?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin/fork) + +## 798\. Smallest Rotation with Highest Score + +Hard + +You are given an array `nums`. You can rotate it by a non-negative integer `k` so that the array becomes `[nums[k], nums[k + 1], ... nums[nums.length - 1], nums[0], nums[1], ..., nums[k-1]]`. Afterward, any entries that are less than or equal to their index are worth one point. + +* For example, if we have `nums = [2,4,1,3,0]`, and we rotate by `k = 2`, it becomes `[1,3,0,2,4]`. This is worth `3` points because `1 > 0` [no points], `3 > 1` [no points], `0 <= 2` [one point], `2 <= 3` [one point], `4 <= 4` [one point]. + +Return _the rotation index_ `k` _that corresponds to the highest score we can achieve if we rotated_ `nums` _by it_. If there are multiple answers, return the smallest such index `k`. + +**Example 1:** + +**Input:** nums = [2,3,1,4,0] + +**Output:** 3 + +**Explanation:** Scores for each k are listed below: + +k = 0, nums = [2,3,1,4,0], score 2 + +k = 1, nums = [3,1,4,0,2], score 3 + +k = 2, nums = [1,4,0,2,3], score 3 + +k = 3, nums = [4,0,2,3,1], score 4 + +k = 4, nums = [0,2,3,1,4], score 3 So we should choose + +k = 3, which has the highest score. + +**Example 2:** + +**Input:** nums = [1,3,0,2,4] + +**Output:** 0 + +**Explanation:** nums will always have 3 points no matter how it shifts. So we will choose the smallest k, which is 0. + +**Constraints:** + +* 1 <= nums.length <= 105 +* `0 <= nums[i] < nums.length` + +## Solution + +```kotlin +class Solution { + // nums[i] will be in the range [0, nums.length]. + // At which positions will we lose points? The answer is k = i - nums[i] + 1. + // We need to accumulate points we have lost from previous rotations using prefix sum except one + // we did not lose. + fun bestRotation(nums: IntArray): Int { + val n = nums.size + var res = 0 + val change = IntArray(n) + for (i in 0 until n) { + change[(i - nums[i] + 1 + n) % n]-- + } + for (i in 1 until n) { + change[i] += change[i - 1] + 1 + res = if (change[i] > change[res]) i else res + } + return res + } +} +``` \ No newline at end of file diff --git a/src/main/kotlin/g0701_0800/s0799_champagne_tower/readme.md b/src/main/kotlin/g0701_0800/s0799_champagne_tower/readme.md new file mode 100644 index 00000000..4f87b550 --- /dev/null +++ b/src/main/kotlin/g0701_0800/s0799_champagne_tower/readme.md @@ -0,0 +1,80 @@ +[![](https://img.shields.io/github/stars/javadev/LeetCode-in-Kotlin?label=Stars&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin) +[![](https://img.shields.io/github/forks/javadev/LeetCode-in-Kotlin?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin/fork) + +## 799\. Champagne Tower + +Medium + +We stack glasses in a pyramid, where the **first** row has `1` glass, the **second** row has `2` glasses, and so on until the 100th row. Each glass holds one cup of champagne. + +Then, some champagne is poured into the first glass at the top. When the topmost glass is full, any excess liquid poured will fall equally to the glass immediately to the left and right of it. When those glasses become full, any excess champagne will fall equally to the left and right of those glasses, and so on. (A glass at the bottom row has its excess champagne fall on the floor.) + +For example, after one cup of champagne is poured, the top most glass is full. After two cups of champagne are poured, the two glasses on the second row are half full. After three cups of champagne are poured, those two cups become full - there are 3 full glasses total now. After four cups of champagne are poured, the third row has the middle glass half full, and the two outside glasses are a quarter full, as pictured below. + +![](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/03/09/tower.png) + +Now after pouring some non-negative integer cups of champagne, return how full the jth glass in the ith row is (both `i` and `j` are 0-indexed.) + +**Example 1:** + +**Input:** poured = 1, query\_row = 1, query\_glass = 1 + +**Output:** 0.00000 + +**Explanation:** We poured 1 cup of champange to the top glass of the tower (which is indexed as (0, 0)). There will be no excess liquid so all the glasses under the top glass will remain empty. + +**Example 2:** + +**Input:** poured = 2, query\_row = 1, query\_glass = 1 + +**Output:** 0.50000 + +**Explanation:** We poured 2 cups of champange to the top glass of the tower (which is indexed as (0, 0)). There is one cup of excess liquid. The glass indexed as (1, 0) and the glass indexed as (1, 1) will share the excess liquid equally, and each will get half cup of champange. + +**Example 3:** + +**Input:** poured = 100000009, query\_row = 33, query\_glass = 17 + +**Output:** 1.00000 + +**Constraints:** + +* 0 <= poured <= 109 +* `0 <= query_glass <= query_row < 100` + +## Solution + +```kotlin +class Solution { + fun champagneTower(poured: Int, queryRow: Int, queryGlass: Int): Double { + var curRow = 0 + // first row + var cur = doubleArrayOf(poured.toDouble()) + // second row + var next = DoubleArray(2) + var spilled: Boolean + do { + spilled = false + for (i in cur.indices) { + // spilling, put the excess into the next row. + if (cur[i] > 1) { + val spilledAmount = cur[i] - 1 + cur[i] = 1.0 + next[i] += spilledAmount / 2 + next[i + 1] = spilledAmount / 2 + spilled = true + } + } + // got to the desired row, return the glass amount + if (curRow == queryRow) { + return cur[queryGlass] + } + cur = next + curRow++ + next = DoubleArray(curRow + 2) + } while (spilled) + // spill did not happen to the desired row + return 0.0 + } +} +``` \ No newline at end of file diff --git a/src/main/kotlin/g0801_0900/s0801_minimum_swaps_to_make_sequences_increasing/readme.md b/src/main/kotlin/g0801_0900/s0801_minimum_swaps_to_make_sequences_increasing/readme.md new file mode 100644 index 00000000..88e28fbb --- /dev/null +++ b/src/main/kotlin/g0801_0900/s0801_minimum_swaps_to_make_sequences_increasing/readme.md @@ -0,0 +1,60 @@ +[![](https://img.shields.io/github/stars/javadev/LeetCode-in-Kotlin?label=Stars&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin) +[![](https://img.shields.io/github/forks/javadev/LeetCode-in-Kotlin?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin/fork) + +## 801\. Minimum Swaps To Make Sequences Increasing + +Hard + +You are given two integer arrays of the same length `nums1` and `nums2`. In one operation, you are allowed to swap `nums1[i]` with `nums2[i]`. + +* For example, if nums1 = [1,2,3,8], and nums2 = [5,6,7,4], you can swap the element at `i = 3` to obtain `nums1 = [1,2,3,4]` and `nums2 = [5,6,7,8]`. + +Return _the minimum number of needed operations to make_ `nums1` _and_ `nums2` _**strictly increasing**_. The test cases are generated so that the given input always makes it possible. + +An array `arr` is **strictly increasing** if and only if `arr[0] < arr[1] < arr[2] < ... < arr[arr.length - 1]`. + +**Example 1:** + +**Input:** nums1 = [1,3,5,4], nums2 = [1,2,3,7] + +**Output:** 1 + +**Explanation:** Swap nums1[3] and nums2[3]. Then the sequences are: nums1 = [1, 3, 5, 7] and nums2 = [1, 2, 3, 4] which are both strictly increasing. + +**Example 2:** + +**Input:** nums1 = [0,3,5,8,9], nums2 = [2,1,4,6,9] + +**Output:** 1 + +**Constraints:** + +* 2 <= nums1.length <= 105 +* `nums2.length == nums1.length` +* 0 <= nums1[i], nums2[i] <= 2 * 105 + +## Solution + +```kotlin +class Solution { + fun minSwap(listA: IntArray, listB: IntArray): Int { + val dp = IntArray(2) + dp[1] = 1 + for (i in 1 until listA.size) { + var a = Int.MAX_VALUE + var b = Int.MAX_VALUE + if (listA[i] > listA[i - 1] && listB[i] > listB[i - 1]) { + a = dp[0] + b = dp[1] + } + if (listA[i] > listB[i - 1] && listB[i] > listA[i - 1]) { + a = a.coerceAtMost(dp[1]) + b = b.coerceAtMost(dp[0]) + } + dp[0] = a + dp[1] = b + 1 + } + return dp[0].coerceAtMost(dp[1]) + } +} +``` \ No newline at end of file diff --git a/src/main/kotlin/g0801_0900/s0802_find_eventual_safe_states/readme.md b/src/main/kotlin/g0801_0900/s0802_find_eventual_safe_states/readme.md new file mode 100644 index 00000000..97f0501a --- /dev/null +++ b/src/main/kotlin/g0801_0900/s0802_find_eventual_safe_states/readme.md @@ -0,0 +1,71 @@ +[![](https://img.shields.io/github/stars/javadev/LeetCode-in-Kotlin?label=Stars&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin) +[![](https://img.shields.io/github/forks/javadev/LeetCode-in-Kotlin?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin/fork) + +## 802\. Find Eventual Safe States + +Medium + +There is a directed graph of `n` nodes with each node labeled from `0` to `n - 1`. The graph is represented by a **0-indexed** 2D integer array `graph` where `graph[i]` is an integer array of nodes adjacent to node `i`, meaning there is an edge from node `i` to each node in `graph[i]`. + +A node is a **terminal node** if there are no outgoing edges. A node is a **safe node** if every possible path starting from that node leads to a **terminal node** (or another safe node). + +Return _an array containing all the **safe nodes** of the graph_. The answer should be sorted in **ascending** order. + +**Example 1:** + +![Illustration of graph](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/03/17/picture1.png) + +**Input:** graph = \[\[1,2],[2,3],[5],[0],[5],[],[]] + +**Output:** [2,4,5,6] + +**Explanation:** The given graph is shown above. Nodes 5 and 6 are terminal nodes as there are no outgoing edges from either of them. Every path starting at nodes 2, 4, 5, and 6 all lead to either node 5 or 6. + +**Example 2:** + +**Input:** graph = \[\[1,2,3,4],[1,2],[3,4],[0,4],[]] + +**Output:** [4] + +**Explanation:** Only node 4 is a terminal node, and every path starting at node 4 leads to node 4. + +**Constraints:** + +* `n == graph.length` +* 1 <= n <= 104 +* `0 <= graph[i].length <= n` +* `0 <= graph[i][j] <= n - 1` +* `graph[i]` is sorted in a strictly increasing order. +* The graph may contain self-loops. +* The number of edges in the graph will be in the range [1, 4 * 104]. + +## Solution + +```kotlin +class Solution { + fun eventualSafeNodes(graph: Array): List { + val res: MutableList = ArrayList() + val vis = IntArray(graph.size) + for (i in graph.indices) { + if (dfs(graph, i, vis)) { + res.add(i) + } + } + return res + } + + private fun dfs(graph: Array, src: Int, vis: IntArray): Boolean { + if (vis[src] != 0) { + return vis[src] == 2 + } + vis[src] = 1 + for (x in graph[src]) { + if (!dfs(graph, x, vis)) { + return false + } + } + vis[src] = 2 + return true + } +} +``` \ No newline at end of file diff --git a/src/main/kotlin/g0801_0900/s0803_bricks_falling_when_hit/readme.md b/src/main/kotlin/g0801_0900/s0803_bricks_falling_when_hit/readme.md new file mode 100644 index 00000000..91323337 --- /dev/null +++ b/src/main/kotlin/g0801_0900/s0803_bricks_falling_when_hit/readme.md @@ -0,0 +1,133 @@ +[![](https://img.shields.io/github/stars/javadev/LeetCode-in-Kotlin?label=Stars&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin) +[![](https://img.shields.io/github/forks/javadev/LeetCode-in-Kotlin?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin/fork) + +## 803\. Bricks Falling When Hit + +Hard + +You are given an `m x n` binary `grid`, where each `1` represents a brick and `0` represents an empty space. A brick is **stable** if: + +* It is directly connected to the top of the grid, or +* At least one other brick in its four adjacent cells is **stable**. + +You are also given an array `hits`, which is a sequence of erasures we want to apply. Each time we want to erase the brick at the location hits[i] = (rowi, coli). The brick on that location (if it exists) will disappear. Some other bricks may no longer be stable because of that erasure and will **fall**. Once a brick falls, it is **immediately** erased from the `grid` (i.e., it does not land on other stable bricks). + +Return _an array_ `result`_, where each_ `result[i]` _is the number of bricks that will **fall** after the_ ith _erasure is applied._ + +**Note** that an erasure may refer to a location with no brick, and if it does, no bricks drop. + +**Example 1:** + +**Input:** grid = \[\[1,0,0,0],[1,1,1,0]], hits = \[\[1,0]] + +**Output:** [2] + +**Explanation:** Starting with the grid: + +[[1,0,0,0], [1,1,1,0]] + +We erase the underlined brick at (1,0), resulting in the grid: + +[[1,0,0,0], [0,1,1,0]] + +The two underlined bricks are no longer stable as they are no longer connected to the top nor adjacent to another stable brick, so they will fall. The resulting grid is: + +[[1,0,0,0], [0,0,0,0]] + +Hence the result is [2]. + +**Example 2:** + +**Input:** grid = \[\[1,0,0,0],[1,1,0,0]], hits = \[\[1,1],[1,0]] + +**Output:** [0,0] + +**Explanation:** Starting with the grid: + +[[1,0,0,0], [1,1,0,0]] + +We erase the underlined brick at (1,1), resulting in the grid: + +[[1,0,0,0], [1,0,0,0]] + +All remaining bricks are still stable, so no bricks fall. The grid remains the same: + +[[1,0,0,0], [1,0,0,0]] + +Next, we erase the underlined brick at (1,0), resulting in the grid: + +[[1,0,0,0], [0,0,0,0]] + +Once again, all remaining bricks are still stable, so no bricks fall. + +Hence the result is [0,0]. + +**Constraints:** + +* `m == grid.length` +* `n == grid[i].length` +* `1 <= m, n <= 200` +* `grid[i][j]` is `0` or `1`. +* 1 <= hits.length <= 4 * 104 +* `hits[i].length == 2` +* 0 <= xi <= m - 1 +* 0 <= yi <= n - 1 +* All (xi, yi) are unique. + +## Solution + +```kotlin +class Solution { + private val dirs = arrayOf(intArrayOf(1, 0), intArrayOf(-1, 0), intArrayOf(0, 1), intArrayOf(0, -1)) + fun hitBricks(grid: Array, hits: Array): IntArray { + val cols = grid[0].size + for (hit in hits) { + val x = hit[0] + val y = hit[1] + grid[x][y]-- + } + val row = 0 + for (col in 0 until cols) { + dfs(row, col, grid) + } + val res = IntArray(hits.size) + for (i in hits.indices.reversed()) { + val x = hits[i][0] + val y = hits[i][1] + grid[x][y]++ + if (grid[x][y] == 1 && isConnectedToRoof(x, y, grid)) { + res[i] = dfs(x, y, grid) - 1 + } + } + return res + } + + private fun dfs(i: Int, j: Int, grid: Array): Int { + if (i < 0 || i >= grid.size || j < 0 || j >= grid[0].size || grid[i][j] != 1) { + return 0 + } + grid[i][j] = 2 + return ( + dfs(i + 1, j, grid) + + dfs(i - 1, j, grid) + + dfs(i, j + 1, grid) + + dfs(i, j - 1, grid) + + 1 + ) + } + + private fun isConnectedToRoof(i: Int, j: Int, grid: Array): Boolean { + if (i == 0) { + return true + } + for (d in dirs) { + val x = i + d[0] + val y = j + d[1] + if (x >= 0 && x < grid.size && y >= 0 && y < grid[0].size && grid[x][y] == 2) { + return true + } + } + return false + } +} +``` \ No newline at end of file diff --git a/src/main/kotlin/g0801_0900/s0804_unique_morse_code_words/readme.md b/src/main/kotlin/g0801_0900/s0804_unique_morse_code_words/readme.md new file mode 100644 index 00000000..36d82244 --- /dev/null +++ b/src/main/kotlin/g0801_0900/s0804_unique_morse_code_words/readme.md @@ -0,0 +1,75 @@ +[![](https://img.shields.io/github/stars/javadev/LeetCode-in-Kotlin?label=Stars&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin) +[![](https://img.shields.io/github/forks/javadev/LeetCode-in-Kotlin?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin/fork) + +## 804\. Unique Morse Code Words + +Easy + +International Morse Code defines a standard encoding where each letter is mapped to a series of dots and dashes, as follows: + +* `'a'` maps to `".-"`, +* `'b'` maps to `"-..."`, +* `'c'` maps to `"-.-."`, and so on. + +For convenience, the full table for the `26` letters of the English alphabet is given below: + +[".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."] + +Given an array of strings `words` where each word can be written as a concatenation of the Morse code of each letter. + +* For example, `"cab"` can be written as `"-.-..--..."`, which is the concatenation of `"-.-."`, `".-"`, and `"-..."`. We will call such a concatenation the **transformation** of a word. + +Return _the number of different **transformations** among all words we have_. + +**Example 1:** + +**Input:** words = ["gin","zen","gig","msg"] + +**Output:** 2 + +**Explanation:** The transformation of each word is: + +"gin" -> "--...-." + +"zen" -> "--...-." + +"gig" -> "--...--." + +"msg" -> "--...--." + +There are 2 different transformations: "--...-." and "--...--.". + +**Example 2:** + +**Input:** words = ["a"] + +**Output:** 1 + +**Constraints:** + +* `1 <= words.length <= 100` +* `1 <= words[i].length <= 12` +* `words[i]` consists of lowercase English letters. + +## Solution + +```kotlin +class Solution { + fun uniqueMorseRepresentations(words: Array): Int { + val morse = arrayOf( + ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", + "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", + "-.--", "--.." + ) + val set: MutableSet = HashSet() + for (word in words) { + val temp = StringBuilder() + for (c in word.toCharArray()) { + temp.append(morse[c.code - 'a'.code]) + } + set.add(temp.toString()) + } + return set.size + } +} +``` \ No newline at end of file diff --git a/src/main/kotlin/g0801_0900/s0805_split_array_with_same_average/readme.md b/src/main/kotlin/g0801_0900/s0805_split_array_with_same_average/readme.md new file mode 100644 index 00000000..86eeb1d3 --- /dev/null +++ b/src/main/kotlin/g0801_0900/s0805_split_array_with_same_average/readme.md @@ -0,0 +1,85 @@ +[![](https://img.shields.io/github/stars/javadev/LeetCode-in-Kotlin?label=Stars&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin) +[![](https://img.shields.io/github/forks/javadev/LeetCode-in-Kotlin?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/javadev/LeetCode-in-Kotlin/fork) + +## 805\. Split Array With Same Average + +Hard + +You are given an integer array `nums`. + +You should move each element of `nums` into one of the two arrays `A` and `B` such that `A` and `B` are non-empty, and `average(A) == average(B)`. + +Return `true` if it is possible to achieve that and `false` otherwise. + +**Note** that for an array `arr`, `average(arr)` is the sum of all the elements of `arr` over the length of `arr`. + +**Example 1:** + +**Input:** nums = [1,2,3,4,5,6,7,8] + +**Output:** true + +**Explanation:** We can split the array into [1,4,5,8] and [2,3,6,7], and both of them have an average of 4.5. + +**Example 2:** + +**Input:** nums = [3,1] + +**Output:** false + +**Constraints:** + +* `1 <= nums.length <= 30` +* 0 <= nums[i] <= 104 + +## Solution + +```kotlin +@Suppress("NAME_SHADOWING") +class Solution { + private lateinit var nums: IntArray + private lateinit var sums: IntArray + + fun splitArraySameAverage(nums: IntArray): Boolean { + val len = nums.size + if (len == 1) { + return false + } + nums.sort() + sums = IntArray(len + 1) + for (i in 0 until len) { + sums[i + 1] = sums[i] + nums[i] + } + val sum = sums[len] + this.nums = nums + var i = 1 + val stop = len / 2 + while (i <= stop) { + if (sum * i % len == 0 && findSum(i, len, sum * i / len)) { + return true + } + i++ + } + return false + } + + private fun findSum(k: Int, pos: Int, target: Int): Boolean { + var pos = pos + if (k == 1) { + while (true) { + if (nums[--pos] <= target) { + break + } + } + return nums[pos] == target + } + var i = pos + while (sums[i] - sums[i-- - k] >= target) { + if (sums[k - 1] <= target - nums[i] && findSum(k - 1, i, target - nums[i])) { + return true + } + } + return false + } +} +``` \ No newline at end of file