diff --git a/README.md b/README.md index 7a7fb31..ef5837c 100644 --- a/README.md +++ b/README.md @@ -319,6 +319,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0392 |[Is Subsequence](src/main/ts/g0301_0400/s0392_is_subsequence/solution.ts)| Easy | String, Dynamic_Programming, Two_Pointers | 0 | 100.00 | 1143 |[Longest Common Subsequence](src/main/ts/g1101_1200/s1143_longest_common_subsequence/solution.ts)| Medium | Top_100_Liked_Questions, String, Dynamic_Programming, Big_O_Time_O(n\*m)_Space_O(n\*m) | 50 | 69.40 | 0072 |[Edit Distance](src/main/ts/g0001_0100/s0072_edit_distance/solution.ts)| Medium | Top_100_Liked_Questions, String, Dynamic_Programming, Big_O_Time_O(n^2)_Space_O(n2) | 6 | 93.83 @@ -579,6 +580,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0433 |[Minimum Genetic Mutation](src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/solution.ts)| Medium | String, Hash_Table, Breadth_First_Search | 0 | 100.00 | 0127 |[Word Ladder](src/main/ts/g0101_0200/s0127_word_ladder/solution.ts)| Hard | Top_Interview_Questions, String, Hash_Table, Breadth_First_Search | 41 | 95.63 #### Day 13 Graph Theory @@ -655,6 +657,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- | 0205 |[Isomorphic Strings](src/main/ts/g0201_0300/s0205_isomorphic_strings/solution.ts)| Easy | String, Hash_Table | 3 | 96.02 +| 0392 |[Is Subsequence](src/main/ts/g0301_0400/s0392_is_subsequence/solution.ts)| Easy | String, Dynamic_Programming, Two_Pointers | 0 | 100.00 #### Day 3 Linked List @@ -918,6 +921,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0392 |[Is Subsequence](src/main/ts/g0301_0400/s0392_is_subsequence/solution.ts)| Easy | String, Dynamic_Programming, Two_Pointers | 0 | 100.00 | 0125 |[Valid Palindrome](src/main/ts/g0101_0200/s0125_valid_palindrome/solution.ts)| Easy | Top_Interview_Questions, String, Two_Pointers | 0 | 100.00 | 0026 |[Remove Duplicates from Sorted Array](src/main/ts/g0001_0100/s0026_remove_duplicates_from_sorted_array/solution.ts)| Easy | Top_Interview_Questions, Array, Two_Pointers | 0 | 100.00 | 0042 |[Trapping Rain Water](src/main/ts/g0001_0100/s0042_trapping_rain_water/solution.ts)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, Array, Dynamic_Programming, Two_Pointers, Stack, Monotonic_Stack, Big_O_Time_O(n)_Space_O(1) | 0 | 100.00 @@ -1062,6 +1066,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- | 0125 |[Valid Palindrome](src/main/ts/g0101_0200/s0125_valid_palindrome/solution.ts)| Easy | Top_Interview_Questions, String, Two_Pointers | 0 | 100.00 +| 0392 |[Is Subsequence](src/main/ts/g0301_0400/s0392_is_subsequence/solution.ts)| Easy | String, Dynamic_Programming, Two_Pointers | 0 | 100.00 | 0167 |[Two Sum II - Input Array Is Sorted](src/main/ts/g0101_0200/s0167_two_sum_ii_input_array_is_sorted/solution.ts)| Medium | Array, Binary_Search, Two_Pointers | 0 | 100.00 | 0011 |[Container With Most Water](src/main/ts/g0001_0100/s0011_container_with_most_water/solution.ts)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Greedy, Two_Pointers, Big_O_Time_O(n)_Space_O(1) | 2 | 80.13 | 0015 |[3Sum](src/main/ts/g0001_0100/s0015_3sum/solution.ts)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Two_Pointers, Big_O_Time_O(n\*log(n))_Space_O(n^2) | 30 | 91.56 @@ -1089,6 +1094,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0383 |[Ransom Note](src/main/ts/g0301_0400/s0383_ransom_note/solution.ts)| Easy | String, Hash_Table, Counting | 4 | 97.40 | 0205 |[Isomorphic Strings](src/main/ts/g0201_0300/s0205_isomorphic_strings/solution.ts)| Easy | String, Hash_Table | 3 | 96.02 | 0290 |[Word Pattern](src/main/ts/g0201_0300/s0290_word_pattern/solution.ts)| Easy | String, Hash_Table | 0 | 100.00 | 0242 |[Valid Anagram](src/main/ts/g0201_0300/s0242_valid_anagram/solution.ts)| Easy | String, Hash_Table, Sorting | 4 | 97.99 @@ -1177,6 +1183,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0433 |[Minimum Genetic Mutation](src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/solution.ts)| Medium | String, Hash_Table, Breadth_First_Search | 0 | 100.00 | 0127 |[Word Ladder](src/main/ts/g0101_0200/s0127_word_ladder/solution.ts)| Hard | Top_Interview_Questions, String, Hash_Table, Breadth_First_Search | 41 | 95.63 #### Top Interview 150 Trie @@ -1205,6 +1212,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. |-|-|-|-|-|- | 0108 |[Convert Sorted Array to Binary Search Tree](src/main/ts/g0101_0200/s0108_convert_sorted_array_to_binary_search_tree/solution.ts)| Easy | Top_Interview_Questions, Array, Tree, Binary_Tree, Binary_Search_Tree, Divide_and_Conquer | 0 | 100.00 | 0148 |[Sort List](src/main/ts/g0101_0200/s0148_sort_list/solution.ts)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Sorting, Two_Pointers, Linked_List, Divide_and_Conquer, Merge_Sort, Big_O_Time_O(log(N))_Space_O(log(N)) | 36 | 44.94 +| 0427 |[Construct Quad Tree](src/main/ts/g0401_0500/s0427_construct_quad_tree/solution.ts)| Medium | Array, Tree, Matrix, Divide_and_Conquer | ew 150 | ew 150 Divide and Conquer | 0023 |[Merge k Sorted Lists](src/main/ts/g0001_0100/s0023_merge_k_sorted_lists/solution.ts)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, Heap_Priority_Queue, Linked_List, Divide_and_Conquer, Merge_Sort, Big_O_Time_O(k\*n\*log(k))_Space_O(log(k)) | 4 | 97.65 #### Top Interview 150 Kadane's Algorithm @@ -1230,6 +1238,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- | 0215 |[Kth Largest Element in an Array](src/main/ts/g0201_0300/s0215_kth_largest_element_in_an_array/solution.ts)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Heap_Priority_Queue, Divide_and_Conquer, Quickselect, Big_O_Time_O(n\*log(n))_Space_O(log(n)) | 4 | 99.64 +| 0373 |[Find K Pairs with Smallest Sums](src/main/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/solution.ts)| Medium | Array, Heap_Priority_Queue | 42 | 85.15 | 0295 |[Find Median from Data Stream](src/main/ts/g0201_0300/s0295_find_median_from_data_stream/solution.ts)| Hard | Top_100_Liked_Questions, Sorting, Two_Pointers, Design, Heap_Priority_Queue, Data_Stream, Big_O_Time_O(n\*log_n)_Space_O(n) | 106 | 92.31 #### Top Interview 150 Bit Manipulation @@ -1315,6 +1324,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0383 |[Ransom Note](src/main/ts/g0301_0400/s0383_ransom_note/solution.ts)| Easy | String, Hash_Table, Counting | 4 | 97.40 | 0242 |[Valid Anagram](src/main/ts/g0201_0300/s0242_valid_anagram/solution.ts)| Easy | String, Hash_Table, Sorting | 4 | 97.99 #### Day 7 Linked List @@ -1741,8 +1751,13 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated. | 0494 |[Target Sum](src/main/ts/g0401_0500/s0494_target_sum/solution.ts)| Medium | Array, Dynamic_Programming, Backtracking, Big_O_Time_O(n\*(sum+s))_Space_O(n\*(sum+s)) | 24 | 83.43 | 0438 |[Find All Anagrams in a String](src/main/ts/g0401_0500/s0438_find_all_anagrams_in_a_string/solution.ts)| Medium | Top_100_Liked_Questions, String, Hash_Table, Sliding_Window, Algorithm_II_Day_5_Sliding_Window, Programming_Skills_II_Day_12, Level_1_Day_12_Sliding_Window/Two_Pointer, Big_O_Time_O(n+m)_Space_O(1) | 8 | 97.80 | 0437 |[Path Sum III](src/main/ts/g0401_0500/s0437_path_sum_iii/solution.ts)| Medium | Depth_First_Search, Tree, Binary_Tree, Level_2_Day_7_Tree, Big_O_Time_O(n)_Space_O(n) | 3 | 86.41 +| 0433 |[Minimum Genetic Mutation](src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/solution.ts)| Medium | String, Hash_Table, Breadth_First_Search, Graph_Theory_I_Day_12_Breadth_First_Search, Top_Interview_150_Graph_BFS | 0 | 100.00 +| 0427 |[Construct Quad Tree](src/main/ts/g0401_0500/s0427_construct_quad_tree/solution.ts)| Medium | Array, Tree, Matrix, Divide_and_Conquer | ew 150 | ew 150 Divide and Conquer | 0416 |[Partition Equal Subset Sum](src/main/ts/g0401_0500/s0416_partition_equal_subset_sum/solution.ts)| Medium | Top_100_Liked_Questions, Array, Dynamic_Programming, Level_2_Day_13_Dynamic_Programming, Big_O_Time_O(n\*sums)_Space_O(n\*sums) | 33 | 93.24 | 0394 |[Decode String](src/main/ts/g0301_0400/s0394_decode_string/solution.ts)| Medium | Top_100_Liked_Questions, String, Stack, Recursion, Level_1_Day_14_Stack, Udemy_Strings, Big_O_Time_O(n)_Space_O(n) | 0 | 100.00 +| 0392 |[Is Subsequence](src/main/ts/g0301_0400/s0392_is_subsequence/solution.ts)| Easy | String, Dynamic_Programming, Two_Pointers, Dynamic_Programming_I_Day_19, Level_1_Day_2_String, Udemy_Two_Pointers, Top_Interview_150_Two_Pointers | 0 | 100.00 +| 0383 |[Ransom Note](src/main/ts/g0301_0400/s0383_ransom_note/solution.ts)| Easy | String, Hash_Table, Counting, Data_Structure_I_Day_6_String, Top_Interview_150_Hashmap | 4 | 97.40 +| 0373 |[Find K Pairs with Smallest Sums](src/main/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/solution.ts)| Medium | Array, Heap_Priority_Queue, Top_Interview_150_Heap | 42 | 85.15 | 0347 |[Top K Frequent Elements](src/main/ts/g0301_0400/s0347_top_k_frequent_elements/solution.ts)| Medium | Top_100_Liked_Questions, Array, Hash_Table, Sorting, Heap_Priority_Queue, Counting, Divide_and_Conquer, Quickselect, Bucket_Sort, Data_Structure_II_Day_20_Heap_Priority_Queue, Big_O_Time_O(n\*log(n))_Space_O(k) | 7 | 87.13 | 0338 |[Counting Bits](src/main/ts/g0301_0400/s0338_counting_bits/solution.ts)| Easy | Dynamic_Programming, Bit_Manipulation, Udemy_Bit_Manipulation, Big_O_Time_O(num)_Space_O(num) | 1 | 89.22 | 0322 |[Coin Change](src/main/ts/g0301_0400/s0322_coin_change/solution.ts)| Medium | Top_100_Liked_Questions, Array, Dynamic_Programming, Breadth_First_Search, Algorithm_II_Day_18_Dynamic_Programming, Dynamic_Programming_I_Day_20, Level_2_Day_12_Dynamic_Programming, Top_Interview_150_1D_DP, Big_O_Time_O(m\*n)_Space_O(amount) | 27 | 89.42 diff --git a/src/main/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/readme.md b/src/main/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/readme.md new file mode 100644 index 0000000..71e2c20 --- /dev/null +++ b/src/main/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/readme.md @@ -0,0 +1,40 @@ +373\. Find K Pairs with Smallest Sums + +Medium + +You are given two integer arrays `nums1` and `nums2` sorted in **ascending order** and an integer `k`. + +Define a pair `(u, v)` which consists of one element from the first array and one element from the second array. + +Return _the_ `k` _pairs_ (u1, v1), (u2, v2), ..., (uk, vk) _with the smallest sums_. + +**Example 1:** + +**Input:** nums1 = [1,7,11], nums2 = [2,4,6], k = 3 + +**Output:** [[1,2],[1,4],[1,6]] + +**Explanation:** The first 3 pairs are returned from the sequence: [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6] + +**Example 2:** + +**Input:** nums1 = [1,1,2], nums2 = [1,2,3], k = 2 + +**Output:** [[1,1],[1,1]] + +**Explanation:** The first 2 pairs are returned from the sequence: [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3] + +**Example 3:** + +**Input:** nums1 = [1,2], nums2 = [3], k = 3 + +**Output:** [[1,3],[2,3]] + +**Explanation:** All possible pairs are returned from the sequence: [1,3],[2,3] + +**Constraints:** + +* 1 <= nums1.length, nums2.length <= 105 +* -109 <= nums1[i], nums2[i] <= 109 +* `nums1` and `nums2` both are sorted in **ascending order**. +* `1 <= k <= 1000` diff --git a/src/main/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/solution.ts b/src/main/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/solution.ts new file mode 100644 index 0000000..79b22dc --- /dev/null +++ b/src/main/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/solution.ts @@ -0,0 +1,86 @@ +// #Medium #Array #Heap_Priority_Queue #Top_Interview_150_Heap +// #2025_04_14_Time_42_ms_(85.15%)_Space_85.10_MB_(76.24%) + +class MinHeap { + private heap: { sum: number; i: number; j: number }[] + + constructor() { + this.heap = [] + } + + push(val: { sum: number; i: number; j: number }) { + this.heap.push(val) + this.bubbleUp() + } + + pop(): { sum: number; i: number; j: number } | undefined { + if (this.heap.length === 0) { + return undefined + } + if (this.heap.length === 1) { + return this.heap.pop() + } + const min = this.heap[0] + this.heap[0] = this.heap.pop()! + this.bubbleDown() + return min + } + + isEmpty(): boolean { + return this.heap.length === 0 + } + + private bubbleUp() { + let index = this.heap.length - 1 + while (index > 0) { + let parentIndex = Math.floor((index - 1) / 2) + if (this.heap[parentIndex].sum <= this.heap[index].sum) { + break + } + ;[this.heap[parentIndex], this.heap[index]] = [this.heap[index], this.heap[parentIndex]] + index = parentIndex + } + } + + private bubbleDown() { + let index = 0 + let length = this.heap.length + while (true) { + let leftChildIndex = 2 * index + 1 + let rightChildIndex = 2 * index + 2 + let smallest = index + if (leftChildIndex < length && this.heap[leftChildIndex].sum < this.heap[smallest].sum) { + smallest = leftChildIndex + } + if (rightChildIndex < length && this.heap[rightChildIndex].sum < this.heap[smallest].sum) { + smallest = rightChildIndex + } + if (smallest === index) { + break + } + ;[this.heap[index], this.heap[smallest]] = [this.heap[smallest], this.heap[index]] + index = smallest + } + } +} + +function kSmallestPairs(nums1: number[], nums2: number[], k: number): number[][] { + let ans: number[][] = [] + if (nums1.length === 0 || nums2.length === 0 || k === 0) { + return ans + } + let minHeap = new MinHeap() + for (let i = 0; i < Math.min(nums1.length, k); i++) { + minHeap.push({ sum: nums1[i] + nums2[0], i, j: 0 }) + } + while (k-- > 0 && !minHeap.isEmpty()) { + let { i, j } = minHeap.pop()! + ans.push([nums1[i], nums2[j]]) + if (j + 1 < nums2.length) { + minHeap.push({ sum: nums1[i] + nums2[j + 1], i, j: j + 1 }) + } + } + return ans +} + +export { kSmallestPairs } diff --git a/src/main/ts/g0301_0400/s0383_ransom_note/readme.md b/src/main/ts/g0301_0400/s0383_ransom_note/readme.md new file mode 100644 index 0000000..6e85a1f --- /dev/null +++ b/src/main/ts/g0301_0400/s0383_ransom_note/readme.md @@ -0,0 +1,30 @@ +383\. Ransom Note + +Easy + +Given two stings `ransomNote` and `magazine`, return `true` if `ransomNote` can be constructed from `magazine` and `false` otherwise. + +Each letter in `magazine` can only be used once in `ransomNote`. + +**Example 1:** + +**Input:** ransomNote = "a", magazine = "b" + +**Output:** false + +**Example 2:** + +**Input:** ransomNote = "aa", magazine = "ab" + +**Output:** false + +**Example 3:** + +**Input:** ransomNote = "aa", magazine = "aab" + +**Output:** true + +**Constraints:** + +* 1 <= ransomNote.length, magazine.length <= 105 +* `ransomNote` and `magazine` consist of lowercase English letters. diff --git a/src/main/ts/g0301_0400/s0383_ransom_note/solution.ts b/src/main/ts/g0301_0400/s0383_ransom_note/solution.ts new file mode 100644 index 0000000..7eb3282 --- /dev/null +++ b/src/main/ts/g0301_0400/s0383_ransom_note/solution.ts @@ -0,0 +1,20 @@ +// #Easy #String #Hash_Table #Counting #Data_Structure_I_Day_6_String #Top_Interview_150_Hashmap +// #2025_04_14_Time_4_ms_(97.40%)_Space_57.51_MB_(84.32%) + +function canConstruct(ransomNote: string, magazine: string): boolean { + const freq: number[] = new Array(26).fill(0) + let remaining = ransomNote.length + for (let i = 0; i < remaining; i++) { + freq[ransomNote.charCodeAt(i) - 97]++ + } + for (let i = 0; i < magazine.length && remaining > 0; i++) { + const index = magazine.charCodeAt(i) - 97 + if (freq[index] > 0) { + freq[index]-- + remaining-- + } + } + return remaining === 0 +} + +export { canConstruct } diff --git a/src/main/ts/g0301_0400/s0392_is_subsequence/readme.md b/src/main/ts/g0301_0400/s0392_is_subsequence/readme.md new file mode 100644 index 0000000..8a6dee7 --- /dev/null +++ b/src/main/ts/g0301_0400/s0392_is_subsequence/readme.md @@ -0,0 +1,27 @@ +392\. Is Subsequence + +Easy + +Given two strings `s` and `t`, return `true` _if_ `s` _is a **subsequence** of_ `t`_, or_ `false` _otherwise_. + +A **subsequence** of a string is a new string that is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (i.e., `"ace"` is a subsequence of `"abcde"` while `"aec"` is not). + +**Example 1:** + +**Input:** s = "abc", t = "ahbgdc" + +**Output:** true + +**Example 2:** + +**Input:** s = "axc", t = "ahbgdc" + +**Output:** false + +**Constraints:** + +* `0 <= s.length <= 100` +* 0 <= t.length <= 104 +* `s` and `t` consist only of lowercase English letters. + +**Follow up:** Suppose there are lots of incoming `s`, say s1, s2, ..., sk where k >= 109, and you want to check one by one to see if `t` has its subsequence. In this scenario, how would you change your code? diff --git a/src/main/ts/g0301_0400/s0392_is_subsequence/solution.ts b/src/main/ts/g0301_0400/s0392_is_subsequence/solution.ts new file mode 100644 index 0000000..be39263 --- /dev/null +++ b/src/main/ts/g0301_0400/s0392_is_subsequence/solution.ts @@ -0,0 +1,25 @@ +// #Easy #String #Dynamic_Programming #Two_Pointers #Dynamic_Programming_I_Day_19 +// #Level_1_Day_2_String #Udemy_Two_Pointers #Top_Interview_150_Two_Pointers +// #2025_04_14_Time_0_ms_(100.00%)_Space_56.51_MB_(36.22%) + +function isSubsequence(s: string, t: string): boolean { + let i = 0 + let j = 0 + const m = s.length + const n = t.length + if (m === 0) { + return true + } + while (j < n) { + if (s[i] === t[j]) { + i++ + if (i === m) { + return true + } + } + j++ + } + return false +} + +export { isSubsequence } diff --git a/src/main/ts/g0401_0500/s0427_construct_quad_tree/readme.md b/src/main/ts/g0401_0500/s0427_construct_quad_tree/readme.md new file mode 100644 index 0000000..9e9dd3d --- /dev/null +++ b/src/main/ts/g0401_0500/s0427_construct_quad_tree/readme.md @@ -0,0 +1,78 @@ +427\. Construct Quad Tree + +Medium + +Given a `n * n` matrix `grid` of `0's` and `1's` only. We want to represent the `grid` with a Quad-Tree. + +Return _the root of the Quad-Tree_ representing the `grid`. + +Notice that you can assign the value of a node to **True** or **False** when `isLeaf` is **False**, and both are **accepted** in the answer. + +A Quad-Tree is a tree data structure in which each internal node has exactly four children. Besides, each node has two attributes: + +* `val`: True if the node represents a grid of 1's or False if the node represents a grid of 0's. +* `isLeaf`: True if the node is leaf node on the tree or False if the node has the four children. +``` + class Node { + public boolean val; + public boolean isLeaf; + public Node topLeft; + public Node topRight; + public Node bottomLeft; + public Node bottomRight; + } +``` +We can construct a Quad-Tree from a two-dimensional area using the following steps: + +1. If the current grid has the same value (i.e all `1's` or all `0's`) set `isLeaf` True and set `val` to the value of the grid and set the four children to Null and stop. +2. If the current grid has different values, set `isLeaf` to False and set `val` to any value and divide the current grid into four sub-grids as shown in the photo. +3. Recurse for each of the children with the proper sub-grid. + +![](https://assets.leetcode.com/uploads/2020/02/11/new_top.png) + +If you want to know more about the Quad-Tree, you can refer to the [wiki](https://en.wikipedia.org/wiki/Quadtree). + +**Quad-Tree format:** + +The output represents the serialized format of a Quad-Tree using level order traversal, where `null` signifies a path terminator where no node exists below. + +It is very similar to the serialization of the binary tree. The only difference is that the node is represented as a list `[isLeaf, val]`. + +If the value of `isLeaf` or `val` is True we represent it as **1** in the list `[isLeaf, val]` and if the value of `isLeaf` or `val` is False we represent it as **0**. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2020/02/11/grid1.png) + +**Input:** grid = [[0,1],[1,0]] + +**Output:** [[0,1],[1,0],[1,1],[1,1],[1,0]] + +**Explanation:** + + The explanation of this example is shown below: + Notice that 0 represnts False and 1 represents True in the photo representing the Quad-Tree. + +![](https://assets.leetcode.com/uploads/2020/02/12/e1tree.png) + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2020/02/12/e2mat.png) + +**Input:** grid = [[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0]] + +**Output:** [[0,1],[1,1],[0,1],[1,1],[1,0],null,null,null,null,[1,0],[1,0],[1,1],[1,1]] + +**Explanation:** + + All values in the grid are not the same. We divide the grid into four sub-grids. + The topLeft, bottomLeft and bottomRight each has the same value. + The topRight have different values so we divide it into 4 sub-grids where each has the same value. + Explanation is shown in the photo below: + +![](https://assets.leetcode.com/uploads/2020/02/12/e2tree.png) + +**Constraints:** + +* `n == grid.length == grid[i].length` +* n == 2x where `0 <= x <= 6` diff --git a/src/main/ts/g0401_0500/s0427_construct_quad_tree/solution.ts b/src/main/ts/g0401_0500/s0427_construct_quad_tree/solution.ts new file mode 100644 index 0000000..7c91dce --- /dev/null +++ b/src/main/ts/g0401_0500/s0427_construct_quad_tree/solution.ts @@ -0,0 +1,92 @@ +// #Medium #Array #Tree #Matrix #Divide_and_Conquer #Top_Interview_150_Divide_and_Conquer + +class _Node { + val: boolean + isLeaf: boolean + topLeft: _Node | null + topRight: _Node | null + bottomLeft: _Node | null + bottomRight: _Node | null + + constructor( + val: boolean, + isLeaf: boolean, + topLeft: _Node | null = null, + topRight: _Node | null = null, + bottomLeft: _Node | null = null, + bottomRight: _Node | null = null, + ) { + this.val = val + this.isLeaf = isLeaf + this.topLeft = topLeft + this.topRight = topRight + this.bottomLeft = bottomLeft + this.bottomRight = bottomRight + } + + toString(): string { + return ( + this.getNode(this) + + this.getNode(this.topLeft) + + this.getNode(this.topRight) + + this.getNode(this.bottomLeft) + + this.getNode(this.bottomRight) + ) + } + + private getNode(node: _Node | null): string { + if (node === null) return 'null' + return `[${node.isLeaf ? '1' : '0'},${node.val ? '1' : '0'}]` + } +} + +/** + * Definition for _Node. + * class _Node { + * val: boolean + * isLeaf: boolean + * topLeft: _Node | null + * topRight: _Node | null + * bottomLeft: _Node | null + * bottomRight: _Node | null + * constructor(val?: boolean, isLeaf?: boolean, topLeft?: _Node, topRight?: _Node, bottomLeft?: _Node, bottomRight?: _Node) { + * this.val = (val===undefined ? false : val) + * this.isLeaf = (isLeaf===undefined ? false : isLeaf) + * this.topLeft = (topLeft===undefined ? null : topLeft) + * this.topRight = (topRight===undefined ? null : topRight) + * this.bottomLeft = (bottomLeft===undefined ? null : bottomLeft) + * this.bottomRight = (bottomRight===undefined ? null : bottomRight) + * } + * } + */ +function construct(grid: number[][]): _Node | null { + return build(grid, 0, 0, grid.length) +} + +function build(grid: number[][], row: number, col: number, size: number): _Node { + if (size === 1) { + return new _Node(grid[row][col] === 1, true) + } + let isSame = true + let firstVal = grid[row][col] + for (let i = row; i < row + size; i++) { + for (let j = col; j < col + size; j++) { + if (grid[i][j] !== firstVal) { + isSame = false + break + } + } + if (!isSame) break + } + if (isSame) { + return new _Node(firstVal === 1, true) + } + let newSize = size / 2 + let topLeft = build(grid, row, col, newSize) + let topRight = build(grid, row, col + newSize, newSize) + let bottomLeft = build(grid, row + newSize, col, newSize) + let bottomRight = build(grid, row + newSize, col + newSize, newSize) + return new _Node(true, false, topLeft, topRight, bottomLeft, bottomRight) +} + +export { construct } diff --git a/src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/readme.md b/src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/readme.md new file mode 100644 index 0000000..852b252 --- /dev/null +++ b/src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/readme.md @@ -0,0 +1,41 @@ +433\. Minimum Genetic Mutation + +Medium + +A gene string can be represented by an 8-character long string, with choices from `'A'`, `'C'`, `'G'`, and `'T'`. + +Suppose we need to investigate a mutation from a gene string `start` to a gene string `end` where one mutation is defined as one single character changed in the gene string. + +* For example, `"AACCGGTT" --> "AACCGGTA"` is one mutation. + +There is also a gene bank `bank` that records all the valid gene mutations. A gene must be in `bank` to make it a valid gene string. + +Given the two gene strings `start` and `end` and the gene bank `bank`, return _the minimum number of mutations needed to mutate from_ `start` _to_ `end`. If there is no such a mutation, return `-1`. + +Note that the starting point is assumed to be valid, so it might not be included in the bank. + +**Example 1:** + +**Input:** start = "AACCGGTT", end = "AACCGGTA", bank = ["AACCGGTA"] + +**Output:** 1 + +**Example 2:** + +**Input:** start = "AACCGGTT", end = "AAACGGTA", bank = ["AACCGGTA","AACCGCTA","AAACGGTA"] + +**Output:** 2 + +**Example 3:** + +**Input:** start = "AAAAACCC", end = "AACCCCCC", bank = ["AAAACCCC","AAACCCCC","AACCCCCC"] + +**Output:** 3 + +**Constraints:** + +* `start.length == 8` +* `end.length == 8` +* `0 <= bank.length <= 10` +* `bank[i].length == 8` +* `start`, `end`, and `bank[i]` consist of only the characters `['A', 'C', 'G', 'T']`. diff --git a/src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/solution.ts b/src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/solution.ts new file mode 100644 index 0000000..1768f7e --- /dev/null +++ b/src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/solution.ts @@ -0,0 +1,41 @@ +// #Medium #String #Hash_Table #Breadth_First_Search #Graph_Theory_I_Day_12_Breadth_First_Search +// #Top_Interview_150_Graph_BFS #2025_04_14_Time_0_ms_(100.00%)_Space_55.27_MB_(71.43%) + +function minMutation(startGene: string, endGene: string, bank: string[]): number { + const isInBank = (set: Set, cur: string): string[] => { + const res: string[] = [] + for (const each of set) { + let diff = 0 + for (let i = 0; i < each.length; i++) { + if (each[i] !== cur[i]) { + diff++ + if (diff > 1) break + } + } + if (diff === 1) { + res.push(each) + } + } + return res + } + const set = new Set(bank) + const queue: string[] = [startGene] + let step = 0 + while (queue.length > 0) { + const curSize = queue.length + for (let i = 0; i < curSize; i++) { + const cur = queue.shift()! + if (cur === endGene) { + return step + } + for (const next of isInBank(set, cur)) { + queue.push(next) + set.delete(next) + } + } + step++ + } + return -1 +} + +export { minMutation } diff --git a/src/test/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/solution.test.ts b/src/test/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/solution.test.ts new file mode 100644 index 0000000..3d634d4 --- /dev/null +++ b/src/test/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/solution.test.ts @@ -0,0 +1,18 @@ +// tslint:disable:no-magic-numbers +import { kSmallestPairs } from 'src/main/ts/g0301_0400/s0373_find_k_pairs_with_smallest_sums/solution' +import { expect, test } from 'vitest' + +test('kSmallestPairs', () => { + expect(kSmallestPairs([1, 7, 11], [2, 4, 6], 3)).toEqual([ + [1, 2], + [1, 4], + [1, 6], + ]) +}) + +test('kSmallestPairs2', () => { + expect(kSmallestPairs([1, 1, 2], [1, 2, 3], 2)).toEqual([ + [1, 1], + [1, 1], + ]) +}) diff --git a/src/test/ts/g0301_0400/s0383_ransom_note/solution.test.ts b/src/test/ts/g0301_0400/s0383_ransom_note/solution.test.ts new file mode 100644 index 0000000..809b0bb --- /dev/null +++ b/src/test/ts/g0301_0400/s0383_ransom_note/solution.test.ts @@ -0,0 +1,15 @@ +// tslint:disable:no-magic-numbers +import { canConstruct } from 'src/main/ts/g0301_0400/s0383_ransom_note/solution' +import { expect, test } from 'vitest' + +test('canConstruct', () => { + expect(canConstruct('a', 'b')).toEqual(false) +}) + +test('canConstruct2', () => { + expect(canConstruct('aa', 'ab')).toEqual(false) +}) + +test('canConstruct3', () => { + expect(canConstruct('aa', 'aab')).toEqual(true) +}) diff --git a/src/test/ts/g0301_0400/s0392_is_subsequence/solution.test.ts b/src/test/ts/g0301_0400/s0392_is_subsequence/solution.test.ts new file mode 100644 index 0000000..8940a9e --- /dev/null +++ b/src/test/ts/g0301_0400/s0392_is_subsequence/solution.test.ts @@ -0,0 +1,11 @@ +// tslint:disable:no-magic-numbers +import { isSubsequence } from 'src/main/ts/g0301_0400/s0392_is_subsequence/solution' +import { expect, test } from 'vitest' + +test('isSubsequence', () => { + expect(isSubsequence('abc', 'ahbgdc')).toEqual(true) +}) + +test('isSubsequence2', () => { + expect(isSubsequence('axc', 'ahbgdc')).toEqual(false) +}) diff --git a/src/test/ts/g0401_0500/s0427_construct_quad_tree/solution.test.ts b/src/test/ts/g0401_0500/s0427_construct_quad_tree/solution.test.ts new file mode 100644 index 0000000..604cee7 --- /dev/null +++ b/src/test/ts/g0401_0500/s0427_construct_quad_tree/solution.test.ts @@ -0,0 +1,27 @@ +// tslint:disable:no-magic-numbers +import { construct } from 'src/main/ts/g0401_0500/s0427_construct_quad_tree/solution' +import { expect, test } from 'vitest' + +test('construct', () => { + expect( + construct([ + [0, 1], + [1, 0], + ])?.toString(), + ).toEqual('[0,1][1,0][1,1][1,1][1,0]') +}) + +test('construct2', () => { + expect( + construct([ + [1, 1, 1, 1, 0, 0, 0, 0], + [1, 1, 1, 1, 0, 0, 0, 0], + [1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 0, 0, 0, 0], + [1, 1, 1, 1, 0, 0, 0, 0], + [1, 1, 1, 1, 0, 0, 0, 0], + [1, 1, 1, 1, 0, 0, 0, 0], + ])?.toString(), + ).toEqual('[0,1][1,1][0,1][1,1][1,0]') +}) diff --git a/src/test/ts/g0401_0500/s0433_minimum_genetic_mutation/solution.test.ts b/src/test/ts/g0401_0500/s0433_minimum_genetic_mutation/solution.test.ts new file mode 100644 index 0000000..a4c03da --- /dev/null +++ b/src/test/ts/g0401_0500/s0433_minimum_genetic_mutation/solution.test.ts @@ -0,0 +1,11 @@ +// tslint:disable:no-magic-numbers +import { minMutation } from 'src/main/ts/g0401_0500/s0433_minimum_genetic_mutation/solution' +import { expect, test } from 'vitest' + +test('minMutation', () => { + expect(minMutation('AACCGGTT', 'AACCGGTA', ['AACCGGTA'])).toEqual(1) +}) + +test('minMutation2', () => { + expect(minMutation('AACCGGTT', 'AAACGGTA', ['AACCGGTA', 'AACCGCTA', 'AAACGGTA'])).toEqual(2) +})