Skip to content

Commit 400bbfa

Browse files
committedApr 15, 2025·
Added tasks 210-433
1 parent 2f06503 commit 400bbfa

File tree

16 files changed

+1392
-0
lines changed

16 files changed

+1392
-0
lines changed
 

‎README.md

Lines changed: 41 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 210\. Course Schedule II
5+
6+
Medium
7+
8+
There are a total of `numCourses` courses you have to take, labeled from `0` to `numCourses - 1`. You are given an array `prerequisites` where <code>prerequisites[i] = [a<sub>i</sub>, b<sub>i</sub>]</code> indicates that you **must** take course <code>b<sub>i</sub></code> first if you want to take course <code>a<sub>i</sub></code>.
9+
10+
* For example, the pair `[0, 1]`, indicates that to take course `0` you have to first take course `1`.
11+
12+
Return _the ordering of courses you should take to finish all courses_. If there are many valid answers, return **any** of them. If it is impossible to finish all courses, return **an empty array**.
13+
14+
**Example 1:**
15+
16+
**Input:** numCourses = 2, prerequisites = \[\[1,0]]
17+
18+
**Output:** [0,1]
19+
20+
**Explanation:**
21+
22+
There are a total of 2 courses to take. To take course 1 you should have finished course 0.
23+
So the correct course order is [0,1].
24+
25+
**Example 2:**
26+
27+
**Input:** numCourses = 4, prerequisites = \[\[1,0],[2,0],[3,1],[3,2]]
28+
29+
**Output:** [0,2,1,3]
30+
31+
**Explanation:**
32+
33+
There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0.
34+
So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3].
35+
36+
**Example 3:**
37+
38+
**Input:** numCourses = 1, prerequisites = []
39+
40+
**Output:** [0]
41+
42+
**Constraints:**
43+
44+
* `1 <= numCourses <= 2000`
45+
* `0 <= prerequisites.length <= numCourses * (numCourses - 1)`
46+
* `prerequisites[i].length == 2`
47+
* <code>0 <= a<sub>i</sub>, b<sub>i</sub> < numCourses</code>
48+
* <code>a<sub>i</sub> != b<sub>i</sub></code>
49+
* All the pairs <code>[a<sub>i</sub>, b<sub>i</sub>]</code> are **distinct**.
50+
51+
## Solution
52+
53+
```typescript
54+
function findOrder(numCourses: number, prerequisites: number[][]): number[] {
55+
let sortedOrder: number[] = []
56+
if (numCourses < 0) return sortedOrder
57+
let inDegree = new Array(numCourses).fill(0),
58+
graph = new Array(numCourses).fill(0).map(() => new Array()),
59+
source = new Array<number>()
60+
prerequisites.forEach((course: number[]) => {
61+
graph[course[1]].push(course[0])
62+
inDegree[course[0]]++
63+
})
64+
inDegree.forEach((value: number, index: number) => {
65+
if (value === 0) {
66+
source.push(index)
67+
}
68+
})
69+
while (source.length > 0) {
70+
const course = source.shift()
71+
if (course === undefined) break
72+
sortedOrder.push(course)
73+
graph[course].forEach((val) => {
74+
inDegree[val]--
75+
if (inDegree[val] === 0) {
76+
source.push(val)
77+
}
78+
})
79+
}
80+
return sortedOrder.length === numCourses ? sortedOrder : []
81+
}
82+
83+
export { findOrder }
84+
```
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 211\. Design Add and Search Words Data Structure
5+
6+
Medium
7+
8+
Design a data structure that supports adding new words and finding if a string matches any previously added string.
9+
10+
Implement the `WordDictionary` class:
11+
12+
* `WordDictionary()` Initializes the object.
13+
* `void addWord(word)` Adds `word` to the data structure, it can be matched later.
14+
* `bool search(word)` Returns `true` if there is any string in the data structure that matches `word` or `false` otherwise. `word` may contain dots `'.'` where dots can be matched with any letter.
15+
16+
**Example:**
17+
18+
**Input**
19+
20+
["WordDictionary","addWord","addWord","addWord","search","search","search","search"] [[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
21+
22+
**Output**
23+
24+
[null,null,null,null,false,true,true,true]
25+
26+
**Explanation**
27+
28+
WordDictionary wordDictionary = new WordDictionary();
29+
wordDictionary.addWord("bad");
30+
wordDictionary.addWord("dad");
31+
wordDictionary.addWord("mad");
32+
wordDictionary.search("pad"); // return False
33+
wordDictionary.search("bad"); // return True
34+
wordDictionary.search(".ad"); // return True
35+
wordDictionary.search("b.."); // return True
36+
37+
**Constraints:**
38+
39+
* `1 <= word.length <= 500`
40+
* `word` in `addWord` consists lower-case English letters.
41+
* `word` in `search` consist of `'.'` or lower-case English letters.
42+
* At most `50000` calls will be made to `addWord` and `search`.
43+
44+
## Solution
45+
46+
```typescript
47+
interface TrieNode {
48+
[key: string]: TrieNode | boolean
49+
}
50+
51+
class WordDictionary {
52+
root: TrieNode
53+
54+
constructor() {
55+
this.root = {}
56+
}
57+
58+
addWord(word: string): void {
59+
let current = this.root
60+
for (let i = 0; i < word.length; i++) {
61+
const letter = word[i]
62+
if (!current.hasOwnProperty(letter)) {
63+
current[letter] = {}
64+
}
65+
current = current[letter] as TrieNode
66+
}
67+
current.end = true
68+
}
69+
70+
search(word: string): boolean {
71+
const searchSubtree = (word: string, index: number, subtree: TrieNode) => {
72+
if (word.length === index) {
73+
return subtree.hasOwnProperty('end')
74+
}
75+
const currentLetter = word[index]
76+
index += 1
77+
78+
if (currentLetter === '.') {
79+
return Object.keys(subtree).some((letter) => searchSubtree(word, index, subtree[letter] as TrieNode))
80+
} else {
81+
if (subtree.hasOwnProperty(currentLetter)) {
82+
return searchSubtree(word, index, subtree[currentLetter] as TrieNode)
83+
} else {
84+
return false
85+
}
86+
}
87+
}
88+
89+
return searchSubtree(word, 0, this.root)
90+
}
91+
}
92+
93+
/**
94+
* Your WordDictionary object will be instantiated and called as such:
95+
* var obj = new WordDictionary()
96+
* obj.addWord(word)
97+
* var param_2 = obj.search(word)
98+
*/
99+
100+
export { WordDictionary }
101+
```
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 212\. Word Search II
5+
6+
Hard
7+
8+
Given an `m x n` `board` of characters and a list of strings `words`, return _all words on the board_.
9+
10+
Each word must be constructed from letters of sequentially adjacent cells, where **adjacent cells** are horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.
11+
12+
**Example 1:**
13+
14+
![](https://assets.leetcode.com/uploads/2020/11/07/search1.jpg)
15+
16+
**Input:** board = \[\["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
17+
18+
**Output:** ["eat","oath"]
19+
20+
**Example 2:**
21+
22+
![](https://assets.leetcode.com/uploads/2020/11/07/search2.jpg)
23+
24+
**Input:** board = \[\["a","b"],["c","d"]], words = ["abcb"]
25+
26+
**Output:** []
27+
28+
**Constraints:**
29+
30+
* `m == board.length`
31+
* `n == board[i].length`
32+
* `1 <= m, n <= 12`
33+
* `board[i][j]` is a lowercase English letter.
34+
* <code>1 <= words.length <= 3 * 10<sup>4</sup></code>
35+
* `1 <= words[i].length <= 10`
36+
* `words[i]` consists of lowercase English letters.
37+
* All the strings of `words` are unique.
38+
39+
## Solution
40+
41+
```typescript
42+
class Tree {
43+
children: Map<string, Tree>
44+
end: string | null
45+
46+
constructor() {
47+
this.children = new Map()
48+
this.end = null
49+
}
50+
51+
static addWord(node: Tree, word: string): void {
52+
let cur = node
53+
for (const char of word) {
54+
if (!cur.children.has(char)) {
55+
cur.children.set(char, new Tree())
56+
}
57+
cur = cur.children.get(char)!
58+
}
59+
cur.end = word
60+
}
61+
62+
static deleteWord(node: Tree, word: string): void {
63+
const stack: [Tree, string][] = []
64+
let cur = node
65+
for (const char of word) {
66+
const next = cur.children.get(char)
67+
if (!next) return
68+
stack.push([cur, char])
69+
cur = next
70+
}
71+
cur.end = null
72+
for (let i = stack.length - 1; i >= 0; i--) {
73+
const [parent, char] = stack[i]
74+
const child = parent.children.get(char)!
75+
if (child.children.size === 0 && child.end === null) {
76+
parent.children.delete(char)
77+
} else {
78+
break
79+
}
80+
}
81+
}
82+
83+
getChild(char: string): Tree | null {
84+
return this.children.get(char) || null
85+
}
86+
87+
len(): number {
88+
return this.children.size
89+
}
90+
}
91+
92+
function findWords(board: string[][], words: string[]): string[] {
93+
if (board.length === 0 || board[0].length === 0) {
94+
return []
95+
}
96+
const root = new Tree()
97+
for (const word of words) {
98+
Tree.addWord(root, word)
99+
}
100+
const collected: string[] = []
101+
for (let i = 0; i < board.length; i++) {
102+
for (let j = 0; j < board[0].length; j++) {
103+
dfs(board, i, j, root, collected, root)
104+
}
105+
}
106+
return collected
107+
}
108+
109+
function dfs(board: string[][], i: number, j: number, cur: Tree, collected: string[], root: Tree): void {
110+
const c = board[i][j]
111+
if (c === '-') {
112+
return
113+
}
114+
const next = cur.getChild(c)
115+
if (!next) {
116+
return
117+
}
118+
if (next.end !== null) {
119+
collected.push(next.end)
120+
const word = next.end
121+
next.end = null
122+
if (next.len() === 0) {
123+
Tree.deleteWord(root, word)
124+
}
125+
}
126+
board[i][j] = '-'
127+
if (i > 0) {
128+
dfs(board, i - 1, j, next, collected, root)
129+
}
130+
if (i + 1 < board.length) {
131+
dfs(board, i + 1, j, next, collected, root)
132+
}
133+
if (j > 0) {
134+
dfs(board, i, j - 1, next, collected, root)
135+
}
136+
if (j + 1 < board[0].length) {
137+
dfs(board, i, j + 1, next, collected, root)
138+
}
139+
board[i][j] = c
140+
}
141+
142+
export { findWords }
143+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 219\. Contains Duplicate II
5+
6+
Easy
7+
8+
Given an integer array `nums` and an integer `k`, return `true` if there are two **distinct indices** `i` and `j` in the array such that `nums[i] == nums[j]` and `abs(i - j) <= k`.
9+
10+
**Example 1:**
11+
12+
**Input:** nums = [1,2,3,1], k = 3
13+
14+
**Output:** true
15+
16+
**Example 2:**
17+
18+
**Input:** nums = [1,0,1,1], k = 1
19+
20+
**Output:** true
21+
22+
**Example 3:**
23+
24+
**Input:** nums = [1,2,3,1,2,3], k = 2
25+
26+
**Output:** false
27+
28+
**Constraints:**
29+
30+
* <code>1 <= nums.length <= 10<sup>5</sup></code>
31+
* <code>-10<sup>9</sup> <= nums[i] <= 10<sup>9</sup></code>
32+
* <code>0 <= k <= 10<sup>5</sup></code>
33+
34+
## Solution
35+
36+
```typescript
37+
function containsNearbyDuplicate(nums: number[], k: number): boolean {
38+
const s = new Set()
39+
for (let i = 0, l = nums.length; i < l; i++) {
40+
if (i > k) {
41+
s.delete(nums[i - k - 1])
42+
}
43+
if (s.has(nums[i])) {
44+
return true
45+
}
46+
s.add(nums[i])
47+
}
48+
return false
49+
}
50+
51+
export { containsNearbyDuplicate }
52+
```
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 222\. Count Complete Tree Nodes
5+
6+
Medium
7+
8+
Given the `root` of a **complete** binary tree, return the number of the nodes in the tree.
9+
10+
According to **[Wikipedia](http://en.wikipedia.org/wiki/Binary_tree#Types_of_binary_trees)**, every level, except possibly the last, is completely filled in a complete binary tree, and all nodes in the last level are as far left as possible. It can have between `1` and <code>2<sup>h</sup></code> nodes inclusive at the last level `h`.
11+
12+
Design an algorithm that runs in less than `O(n)` time complexity.
13+
14+
**Example 1:**
15+
16+
![](https://assets.leetcode.com/uploads/2021/01/14/complete.jpg)
17+
18+
**Input:** root = [1,2,3,4,5,6]
19+
20+
**Output:** 6
21+
22+
**Example 2:**
23+
24+
**Input:** root = []
25+
26+
**Output:** 0
27+
28+
**Example 3:**
29+
30+
**Input:** root = [1]
31+
32+
**Output:** 1
33+
34+
**Constraints:**
35+
36+
* The number of nodes in the tree is in the range <code>[0, 5 * 10<sup>4</sup>]</code>.
37+
* <code>0 <= Node.val <= 5 * 10<sup>4</sup></code>
38+
* The tree is guaranteed to be **complete**.
39+
40+
## Solution
41+
42+
```typescript
43+
import { TreeNode } from '../../com_github_leetcode/treenode'
44+
45+
/**
46+
* Definition for a binary tree node.
47+
* class TreeNode {
48+
* val: number
49+
* left: TreeNode | null
50+
* right: TreeNode | null
51+
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
52+
* this.val = (val===undefined ? 0 : val)
53+
* this.left = (left===undefined ? null : left)
54+
* this.right = (right===undefined ? null : right)
55+
* }
56+
* }
57+
*/
58+
function countNodes(root: TreeNode | null): number {
59+
if (root === null) {
60+
return 0
61+
}
62+
const leftHeight = getLeftHeight(root)
63+
const rightHeight = getRightHeight(root)
64+
if (leftHeight === rightHeight) {
65+
return (1 << leftHeight) - 1
66+
} else {
67+
return 1 + countNodes(root.left) + countNodes(root.right)
68+
}
69+
}
70+
71+
function getLeftHeight(node: TreeNode | null): number {
72+
let height = 0
73+
while (node !== null) {
74+
height++
75+
node = node.left
76+
}
77+
return height
78+
}
79+
80+
function getRightHeight(node: TreeNode | null): number {
81+
let height = 0
82+
while (node !== null) {
83+
height++
84+
node = node.right
85+
}
86+
return height
87+
}
88+
89+
export { countNodes }
90+
```
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 224\. Basic Calculator
5+
6+
Hard
7+
8+
Given a string `s` representing a valid expression, implement a basic calculator to evaluate it, and return _the result of the evaluation_.
9+
10+
**Note:** You are **not** allowed to use any built-in function which evaluates strings as mathematical expressions, such as `eval()`.
11+
12+
**Example 1:**
13+
14+
**Input:** s = "1 + 1"
15+
16+
**Output:** 2
17+
18+
**Example 2:**
19+
20+
**Input:** s = " 2-1 + 2 "
21+
22+
**Output:** 3
23+
24+
**Example 3:**
25+
26+
**Input:** s = "(1+(4+5+2)-3)+(6+8)"
27+
28+
**Output:** 23
29+
30+
**Constraints:**
31+
32+
* <code>1 <= s.length <= 3 * 10<sup>5</sup></code>
33+
* `s` consists of digits, `'+'`, `'-'`, `'('`, `')'`, and `' '`.
34+
* `s` represents a valid expression.
35+
* `'+'` is **not** used as a unary operation (i.e., `"+1"` and `"+(2 + 3)"` is invalid).
36+
* `'-'` could be used as a unary operation (i.e., `"-1"` and `"-(2 + 3)"` is valid).
37+
* There will be no two consecutive operators in the input.
38+
* Every number and running calculation will fit in a signed 32-bit integer.
39+
40+
## Solution
41+
42+
```typescript
43+
function calculate(s: string): number {
44+
let i = 0
45+
46+
function helper(ca: string[]): number {
47+
let num = 0
48+
let prenum = 0
49+
let isPlus = true
50+
while (i < ca.length) {
51+
const c = ca[i]
52+
if (c !== ' ') {
53+
if (c >= '0' && c <= '9') {
54+
num = num * 10 + parseInt(c)
55+
} else if (c === '+') {
56+
prenum += num * (isPlus ? 1 : -1)
57+
isPlus = true
58+
num = 0
59+
} else if (c === '-') {
60+
prenum += num * (isPlus ? 1 : -1)
61+
isPlus = false
62+
num = 0
63+
} else if (c === '(') {
64+
i++
65+
num = helper(ca)
66+
} else if (c === ')') {
67+
prenum += num * (isPlus ? 1 : -1)
68+
return prenum
69+
}
70+
}
71+
i++
72+
}
73+
return prenum + num * (isPlus ? 1 : -1)
74+
}
75+
return helper(s.split(''))
76+
}
77+
78+
export { calculate }
79+
```
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 228\. Summary Ranges
5+
6+
Easy
7+
8+
You are given a **sorted unique** integer array `nums`.
9+
10+
Return _the **smallest sorted** list of ranges that **cover all the numbers in the array exactly**_. That is, each element of `nums` is covered by exactly one of the ranges, and there is no integer `x` such that `x` is in one of the ranges but not in `nums`.
11+
12+
Each range `[a,b]` in the list should be output as:
13+
14+
* `"a->b"` if `a != b`
15+
* `"a"` if `a == b`
16+
17+
**Example 1:**
18+
19+
**Input:** nums = [0,1,2,4,5,7]
20+
21+
**Output:** ["0->2","4->5","7"]
22+
23+
**Explanation:** The ranges are: [0,2] --> "0->2" [4,5] --> "4->5" [7,7] --> "7"
24+
25+
**Example 2:**
26+
27+
**Input:** nums = [0,2,3,4,6,8,9]
28+
29+
**Output:** ["0","2->4","6","8->9"]
30+
31+
**Explanation:** The ranges are: [0,0] --> "0" [2,4] --> "2->4" [6,6] --> "6" [8,9] --> "8->9"
32+
33+
**Example 3:**
34+
35+
**Input:** nums = []
36+
37+
**Output:** []
38+
39+
**Example 4:**
40+
41+
**Input:** nums = [-1]
42+
43+
**Output:** ["-1"]
44+
45+
**Example 5:**
46+
47+
**Input:** nums = [0]
48+
49+
**Output:** ["0"]
50+
51+
**Constraints:**
52+
53+
* `0 <= nums.length <= 20`
54+
* <code>-2<sup>31</sup> <= nums[i] <= 2<sup>31</sup> - 1</code>
55+
* All the values of `nums` are **unique**.
56+
* `nums` is sorted in ascending order.
57+
58+
## Solution
59+
60+
```typescript
61+
function summaryRanges(nums: number[]): string[] {
62+
const ranges: string[] = []
63+
const n = nums.length
64+
if (n === 0) {
65+
return ranges
66+
}
67+
let a = nums[0]
68+
let b = a
69+
let strB = ''
70+
for (let i = 1; i < n; i++) {
71+
if (nums[i] !== b + 1) {
72+
strB = a.toString()
73+
if (a !== b) {
74+
strB += '->' + b.toString()
75+
}
76+
ranges.push(strB)
77+
a = nums[i]
78+
b = a
79+
strB = ''
80+
} else {
81+
b++
82+
}
83+
}
84+
strB = a.toString()
85+
if (a !== b) {
86+
strB += '->' + b.toString()
87+
}
88+
ranges.push(strB)
89+
return ranges
90+
}
91+
92+
export { summaryRanges }
93+
```
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 242\. Valid Anagram
5+
6+
Easy
7+
8+
Given two strings `s` and `t`, return `true` _if_ `t` _is an anagram of_ `s`_, and_ `false` _otherwise_.
9+
10+
**Example 1:**
11+
12+
**Input:** s = "anagram", t = "nagaram"
13+
14+
**Output:** true
15+
16+
**Example 2:**
17+
18+
**Input:** s = "rat", t = "car"
19+
20+
**Output:** false
21+
22+
**Constraints:**
23+
24+
* <code>1 <= s.length, t.length <= 5 * 10<sup>4</sup></code>
25+
* `s` and `t` consist of lowercase English letters.
26+
27+
**Follow up:** What if the inputs contain Unicode characters? How would you adapt your solution to such a case?
28+
29+
## Solution
30+
31+
```typescript
32+
function isAnagram(s: string, t: string): boolean {
33+
if (s.length !== t.length) {
34+
return false
35+
}
36+
let counts = new Array(26).fill(0)
37+
for (let i = 0; i < s.length; ++i) {
38+
counts[s.charCodeAt(i) - 'a'.charCodeAt(0)]++
39+
counts[t.charCodeAt(i) - 'a'.charCodeAt(0)]--
40+
}
41+
return counts.every((c) => c === 0)
42+
}
43+
44+
export { isAnagram }
45+
```
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 289\. Game of Life
5+
6+
Medium
7+
8+
According to [Wikipedia's article](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life): "The **Game of Life**, also known simply as **Life**, is a cellular automaton devised by the British mathematician John Horton Conway in 1970."
9+
10+
The board is made up of an `m x n` grid of cells, where each cell has an initial state: **live** (represented by a `1`) or **dead** (represented by a `0`). Each cell interacts with its [eight neighbors](https://en.wikipedia.org/wiki/Moore_neighborhood) (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):
11+
12+
1. Any live cell with fewer than two live neighbors dies as if caused by under-population.
13+
2. Any live cell with two or three live neighbors lives on to the next generation.
14+
3. Any live cell with more than three live neighbors dies, as if by over-population.
15+
4. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
16+
17+
The next state is created by applying the above rules simultaneously to every cell in the current state, where births and deaths occur simultaneously. Given the current state of the `m x n` grid `board`, return _the next state_.
18+
19+
**Example 1:**
20+
21+
![](https://assets.leetcode.com/uploads/2020/12/26/grid1.jpg)
22+
23+
**Input:** board = \[\[0,1,0],[0,0,1],[1,1,1],[0,0,0]]
24+
25+
**Output:** [[0,0,0],[1,0,1],[0,1,1],[0,1,0]]
26+
27+
**Example 2:**
28+
29+
![](https://assets.leetcode.com/uploads/2020/12/26/grid2.jpg)
30+
31+
**Input:** board = \[\[1,1],[1,0]]
32+
33+
**Output:** [[1,1],[1,1]]
34+
35+
**Constraints:**
36+
37+
* `m == board.length`
38+
* `n == board[i].length`
39+
* `1 <= m, n <= 25`
40+
* `board[i][j]` is `0` or `1`.
41+
42+
**Follow up:**
43+
44+
* Could you solve it in-place? Remember that the board needs to be updated simultaneously: You cannot update some cells first and then use their updated values to update other cells.
45+
* In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches upon the border of the array (i.e., live cells reach the border). How would you address these problems?
46+
47+
## Solution
48+
49+
```typescript
50+
/**
51+
* Do not return anything, modify board in-place instead.
52+
*/
53+
function gameOfLife(board: number[][]): void {
54+
const m = board.length
55+
const n = board[0].length
56+
57+
for (let i = 0; i < m; i++) {
58+
for (let j = 0; j < n; j++) {
59+
const liveNeighbors = countLives(board, i, j, m, n)
60+
if (board[i][j] === 0 && liveNeighbors === 3) {
61+
board[i][j] = 2
62+
} else if (board[i][j] === 1 && (liveNeighbors === 2 || liveNeighbors === 3)) {
63+
board[i][j] = 3
64+
}
65+
}
66+
}
67+
68+
for (let i = 0; i < m; i++) {
69+
for (let j = 0; j < n; j++) {
70+
board[i][j] >>= 1
71+
}
72+
}
73+
}
74+
75+
function countLives(board: number[][], i: number, j: number, m: number, n: number): number {
76+
let lives = 0
77+
for (let r = Math.max(0, i - 1); r <= Math.min(m - 1, i + 1); r++) {
78+
for (let c = Math.max(0, j - 1); c <= Math.min(n - 1, j + 1); c++) {
79+
lives += board[r][c] & 1
80+
}
81+
}
82+
lives -= board[i][j] & 1
83+
return lives
84+
}
85+
86+
export { gameOfLife }
87+
```
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 290\. Word Pattern
5+
6+
Easy
7+
8+
Given a `pattern` and a string `s`, find if `s` follows the same pattern.
9+
10+
Here **follow** means a full match, such that there is a bijection between a letter in `pattern` and a **non-empty** word in `s`.
11+
12+
**Example 1:**
13+
14+
**Input:** pattern = "abba", s = "dog cat cat dog"
15+
16+
**Output:** true
17+
18+
**Example 2:**
19+
20+
**Input:** pattern = "abba", s = "dog cat cat fish"
21+
22+
**Output:** false
23+
24+
**Example 3:**
25+
26+
**Input:** pattern = "aaaa", s = "dog cat cat dog"
27+
28+
**Output:** false
29+
30+
**Example 4:**
31+
32+
**Input:** pattern = "abba", s = "dog dog dog dog"
33+
34+
**Output:** false
35+
36+
**Constraints:**
37+
38+
* `1 <= pattern.length <= 300`
39+
* `pattern` contains only lower-case English letters.
40+
* `1 <= s.length <= 3000`
41+
* `s` contains only lower-case English letters and spaces `' '`.
42+
* `s` **does not contain** any leading or trailing spaces.
43+
* All the words in `s` are separated by a **single space**.
44+
45+
## Solution
46+
47+
```typescript
48+
function wordPattern(pattern: string, s: string): boolean {
49+
const map = new Map<string, string>()
50+
const words = s.split(' ')
51+
if (words.length !== pattern.length) {
52+
return false
53+
}
54+
for (let i = 0; i < pattern.length; i++) {
55+
const char = pattern[i]
56+
const word = words[i]
57+
if (!map.has(char)) {
58+
if ([...map.values()].includes(word)) {
59+
return false
60+
}
61+
map.set(char, word)
62+
} else {
63+
if (map.get(char) !== word) {
64+
return false
65+
}
66+
}
67+
}
68+
return true
69+
}
70+
71+
export { wordPattern }
72+
```
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 373\. Find K Pairs with Smallest Sums
5+
6+
Medium
7+
8+
You are given two integer arrays `nums1` and `nums2` sorted in **ascending order** and an integer `k`.
9+
10+
Define a pair `(u, v)` which consists of one element from the first array and one element from the second array.
11+
12+
Return _the_ `k` _pairs_ <code>(u<sub>1</sub>, v<sub>1</sub>), (u<sub>2</sub>, v<sub>2</sub>), ..., (u<sub>k</sub>, v<sub>k</sub>)</code> _with the smallest sums_.
13+
14+
**Example 1:**
15+
16+
**Input:** nums1 = [1,7,11], nums2 = [2,4,6], k = 3
17+
18+
**Output:** [[1,2],[1,4],[1,6]]
19+
20+
**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]
21+
22+
**Example 2:**
23+
24+
**Input:** nums1 = [1,1,2], nums2 = [1,2,3], k = 2
25+
26+
**Output:** [[1,1],[1,1]]
27+
28+
**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]
29+
30+
**Example 3:**
31+
32+
**Input:** nums1 = [1,2], nums2 = [3], k = 3
33+
34+
**Output:** [[1,3],[2,3]]
35+
36+
**Explanation:** All possible pairs are returned from the sequence: [1,3],[2,3]
37+
38+
**Constraints:**
39+
40+
* <code>1 <= nums1.length, nums2.length <= 10<sup>5</sup></code>
41+
* <code>-10<sup>9</sup> <= nums1[i], nums2[i] <= 10<sup>9</sup></code>
42+
* `nums1` and `nums2` both are sorted in **ascending order**.
43+
* `1 <= k <= 1000`
44+
45+
## Solution
46+
47+
```typescript
48+
class MinHeap {
49+
private heap: { sum: number; i: number; j: number }[]
50+
51+
constructor() {
52+
this.heap = []
53+
}
54+
55+
push(val: { sum: number; i: number; j: number }) {
56+
this.heap.push(val)
57+
this.bubbleUp()
58+
}
59+
60+
pop(): { sum: number; i: number; j: number } | undefined {
61+
if (this.heap.length === 0) {
62+
return undefined
63+
}
64+
if (this.heap.length === 1) {
65+
return this.heap.pop()
66+
}
67+
const min = this.heap[0]
68+
this.heap[0] = this.heap.pop()!
69+
this.bubbleDown()
70+
return min
71+
}
72+
73+
isEmpty(): boolean {
74+
return this.heap.length === 0
75+
}
76+
77+
private bubbleUp() {
78+
let index = this.heap.length - 1
79+
while (index > 0) {
80+
let parentIndex = Math.floor((index - 1) / 2)
81+
if (this.heap[parentIndex].sum <= this.heap[index].sum) {
82+
break
83+
}
84+
;[this.heap[parentIndex], this.heap[index]] = [this.heap[index], this.heap[parentIndex]]
85+
index = parentIndex
86+
}
87+
}
88+
89+
private bubbleDown() {
90+
let index = 0
91+
let length = this.heap.length
92+
while (true) {
93+
let leftChildIndex = 2 * index + 1
94+
let rightChildIndex = 2 * index + 2
95+
let smallest = index
96+
if (leftChildIndex < length && this.heap[leftChildIndex].sum < this.heap[smallest].sum) {
97+
smallest = leftChildIndex
98+
}
99+
if (rightChildIndex < length && this.heap[rightChildIndex].sum < this.heap[smallest].sum) {
100+
smallest = rightChildIndex
101+
}
102+
if (smallest === index) {
103+
break
104+
}
105+
;[this.heap[index], this.heap[smallest]] = [this.heap[smallest], this.heap[index]]
106+
index = smallest
107+
}
108+
}
109+
}
110+
111+
function kSmallestPairs(nums1: number[], nums2: number[], k: number): number[][] {
112+
let ans: number[][] = []
113+
if (nums1.length === 0 || nums2.length === 0 || k === 0) {
114+
return ans
115+
}
116+
let minHeap = new MinHeap()
117+
for (let i = 0; i < Math.min(nums1.length, k); i++) {
118+
minHeap.push({ sum: nums1[i] + nums2[0], i, j: 0 })
119+
}
120+
while (k-- > 0 && !minHeap.isEmpty()) {
121+
let { i, j } = minHeap.pop()!
122+
ans.push([nums1[i], nums2[j]])
123+
if (j + 1 < nums2.length) {
124+
minHeap.push({ sum: nums1[i] + nums2[j + 1], i, j: j + 1 })
125+
}
126+
}
127+
return ans
128+
}
129+
130+
export { kSmallestPairs }
131+
```
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 383\. Ransom Note
5+
6+
Easy
7+
8+
Given two stings `ransomNote` and `magazine`, return `true` if `ransomNote` can be constructed from `magazine` and `false` otherwise.
9+
10+
Each letter in `magazine` can only be used once in `ransomNote`.
11+
12+
**Example 1:**
13+
14+
**Input:** ransomNote = "a", magazine = "b"
15+
16+
**Output:** false
17+
18+
**Example 2:**
19+
20+
**Input:** ransomNote = "aa", magazine = "ab"
21+
22+
**Output:** false
23+
24+
**Example 3:**
25+
26+
**Input:** ransomNote = "aa", magazine = "aab"
27+
28+
**Output:** true
29+
30+
**Constraints:**
31+
32+
* <code>1 <= ransomNote.length, magazine.length <= 10<sup>5</sup></code>
33+
* `ransomNote` and `magazine` consist of lowercase English letters.
34+
35+
## Solution
36+
37+
```typescript
38+
function canConstruct(ransomNote: string, magazine: string): boolean {
39+
const freq: number[] = new Array(26).fill(0)
40+
let remaining = ransomNote.length
41+
for (let i = 0; i < remaining; i++) {
42+
freq[ransomNote.charCodeAt(i) - 97]++
43+
}
44+
for (let i = 0; i < magazine.length && remaining > 0; i++) {
45+
const index = magazine.charCodeAt(i) - 97
46+
if (freq[index] > 0) {
47+
freq[index]--
48+
remaining--
49+
}
50+
}
51+
return remaining === 0
52+
}
53+
54+
export { canConstruct }
55+
```
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 392\. Is Subsequence
5+
6+
Easy
7+
8+
Given two strings `s` and `t`, return `true` _if_ `s` _is a **subsequence** of_ `t`_, or_ `false` _otherwise_.
9+
10+
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).
11+
12+
**Example 1:**
13+
14+
**Input:** s = "abc", t = "ahbgdc"
15+
16+
**Output:** true
17+
18+
**Example 2:**
19+
20+
**Input:** s = "axc", t = "ahbgdc"
21+
22+
**Output:** false
23+
24+
**Constraints:**
25+
26+
* `0 <= s.length <= 100`
27+
* <code>0 <= t.length <= 10<sup>4</sup></code>
28+
* `s` and `t` consist only of lowercase English letters.
29+
30+
**Follow up:** Suppose there are lots of incoming `s`, say <code>s<sub>1</sub>, s<sub>2</sub>, ..., s<sub>k</sub></code> where <code>k >= 10<sup>9</sup></code>, and you want to check one by one to see if `t` has its subsequence. In this scenario, how would you change your code?
31+
32+
## Solution
33+
34+
```typescript
35+
function isSubsequence(s: string, t: string): boolean {
36+
let i = 0
37+
let j = 0
38+
const m = s.length
39+
const n = t.length
40+
if (m === 0) {
41+
return true
42+
}
43+
while (j < n) {
44+
if (s[i] === t[j]) {
45+
i++
46+
if (i === m) {
47+
return true
48+
}
49+
}
50+
j++
51+
}
52+
return false
53+
}
54+
55+
export { isSubsequence }
56+
```
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 427\. Construct Quad Tree
5+
6+
Medium
7+
8+
Given a `n * n` matrix `grid` of `0's` and `1's` only. We want to represent the `grid` with a Quad-Tree.
9+
10+
Return _the root of the Quad-Tree_ representing the `grid`.
11+
12+
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.
13+
14+
A Quad-Tree is a tree data structure in which each internal node has exactly four children. Besides, each node has two attributes:
15+
16+
* `val`: True if the node represents a grid of 1's or False if the node represents a grid of 0's.
17+
* `isLeaf`: True if the node is leaf node on the tree or False if the node has the four children.
18+
```
19+
class Node {
20+
public boolean val;
21+
public boolean isLeaf;
22+
public Node topLeft;
23+
public Node topRight;
24+
public Node bottomLeft;
25+
public Node bottomRight;
26+
}
27+
```
28+
We can construct a Quad-Tree from a two-dimensional area using the following steps:
29+
30+
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.
31+
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.
32+
3. Recurse for each of the children with the proper sub-grid.
33+
34+
![](https://assets.leetcode.com/uploads/2020/02/11/new_top.png)
35+
36+
If you want to know more about the Quad-Tree, you can refer to the [wiki](https://en.wikipedia.org/wiki/Quadtree).
37+
38+
**Quad-Tree format:**
39+
40+
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.
41+
42+
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]`.
43+
44+
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**.
45+
46+
**Example 1:**
47+
48+
![](https://assets.leetcode.com/uploads/2020/02/11/grid1.png)
49+
50+
**Input:** grid = \[\[0,1],[1,0]]
51+
52+
**Output:** [[0,1],[1,0],[1,1],[1,1],[1,0]]
53+
54+
**Explanation:**
55+
56+
The explanation of this example is shown below:
57+
Notice that 0 represnts False and 1 represents True in the photo representing the Quad-Tree.
58+
59+
![](https://assets.leetcode.com/uploads/2020/02/12/e1tree.png)
60+
61+
**Example 2:**
62+
63+
![](https://assets.leetcode.com/uploads/2020/02/12/e2mat.png)
64+
65+
**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]]
66+
67+
**Output:** [[0,1],[1,1],[0,1],[1,1],[1,0],null,null,null,null,[1,0],[1,0],[1,1],[1,1]]
68+
69+
**Explanation:**
70+
71+
All values in the grid are not the same. We divide the grid into four sub-grids.
72+
The topLeft, bottomLeft and bottomRight each has the same value.
73+
The topRight have different values so we divide it into 4 sub-grids where each has the same value.
74+
Explanation is shown in the photo below:
75+
76+
![](https://assets.leetcode.com/uploads/2020/02/12/e2tree.png)
77+
78+
**Constraints:**
79+
80+
* `n == grid.length == grid[i].length`
81+
* <code>n == 2<sup>x</sup></code> where `0 <= x <= 6`
82+
83+
## Solution
84+
85+
```typescript
86+
class _Node {
87+
val: boolean
88+
isLeaf: boolean
89+
topLeft: _Node | null
90+
topRight: _Node | null
91+
bottomLeft: _Node | null
92+
bottomRight: _Node | null
93+
94+
constructor(
95+
val: boolean,
96+
isLeaf: boolean,
97+
topLeft: _Node | null = null,
98+
topRight: _Node | null = null,
99+
bottomLeft: _Node | null = null,
100+
bottomRight: _Node | null = null,
101+
) {
102+
this.val = val
103+
this.isLeaf = isLeaf
104+
this.topLeft = topLeft
105+
this.topRight = topRight
106+
this.bottomLeft = bottomLeft
107+
this.bottomRight = bottomRight
108+
}
109+
110+
toString(): string {
111+
return (
112+
this.getNode(this) +
113+
this.getNode(this.topLeft) +
114+
this.getNode(this.topRight) +
115+
this.getNode(this.bottomLeft) +
116+
this.getNode(this.bottomRight)
117+
)
118+
}
119+
120+
private getNode(node: _Node | null): string {
121+
if (node === null) return 'null'
122+
return `[${node.isLeaf ? '1' : '0'},${node.val ? '1' : '0'}]`
123+
}
124+
}
125+
126+
/**
127+
* Definition for _Node.
128+
* class _Node {
129+
* val: boolean
130+
* isLeaf: boolean
131+
* topLeft: _Node | null
132+
* topRight: _Node | null
133+
* bottomLeft: _Node | null
134+
* bottomRight: _Node | null
135+
* constructor(val?: boolean, isLeaf?: boolean, topLeft?: _Node, topRight?: _Node, bottomLeft?: _Node, bottomRight?: _Node) {
136+
* this.val = (val===undefined ? false : val)
137+
* this.isLeaf = (isLeaf===undefined ? false : isLeaf)
138+
* this.topLeft = (topLeft===undefined ? null : topLeft)
139+
* this.topRight = (topRight===undefined ? null : topRight)
140+
* this.bottomLeft = (bottomLeft===undefined ? null : bottomLeft)
141+
* this.bottomRight = (bottomRight===undefined ? null : bottomRight)
142+
* }
143+
* }
144+
*/
145+
function construct(grid: number[][]): _Node | null {
146+
return build(grid, 0, 0, grid.length)
147+
}
148+
149+
function build(grid: number[][], row: number, col: number, size: number): _Node {
150+
if (size === 1) {
151+
return new _Node(grid[row][col] === 1, true)
152+
}
153+
let isSame = true
154+
let firstVal = grid[row][col]
155+
for (let i = row; i < row + size; i++) {
156+
for (let j = col; j < col + size; j++) {
157+
if (grid[i][j] !== firstVal) {
158+
isSame = false
159+
break
160+
}
161+
}
162+
if (!isSame) break
163+
}
164+
if (isSame) {
165+
return new _Node(firstVal === 1, true)
166+
}
167+
let newSize = size / 2
168+
let topLeft = build(grid, row, col, newSize)
169+
let topRight = build(grid, row, col + newSize, newSize)
170+
let bottomLeft = build(grid, row + newSize, col, newSize)
171+
let bottomRight = build(grid, row + newSize, col + newSize, newSize)
172+
return new _Node(true, false, topLeft, topRight, bottomLeft, bottomRight)
173+
}
174+
175+
export { construct }
176+
```
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
[![](https://img.shields.io/github/stars/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Stars&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript)
2+
[![](https://img.shields.io/github/forks/LeetCode-in-TypeScript/LeetCode-in-TypeScript?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/LeetCode-in-TypeScript/LeetCode-in-TypeScript/fork)
3+
4+
## 433\. Minimum Genetic Mutation
5+
6+
Medium
7+
8+
A gene string can be represented by an 8-character long string, with choices from `'A'`, `'C'`, `'G'`, and `'T'`.
9+
10+
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.
11+
12+
* For example, `"AACCGGTT" --> "AACCGGTA"` is one mutation.
13+
14+
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.
15+
16+
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`.
17+
18+
Note that the starting point is assumed to be valid, so it might not be included in the bank.
19+
20+
**Example 1:**
21+
22+
**Input:** start = "AACCGGTT", end = "AACCGGTA", bank = ["AACCGGTA"]
23+
24+
**Output:** 1
25+
26+
**Example 2:**
27+
28+
**Input:** start = "AACCGGTT", end = "AAACGGTA", bank = ["AACCGGTA","AACCGCTA","AAACGGTA"]
29+
30+
**Output:** 2
31+
32+
**Example 3:**
33+
34+
**Input:** start = "AAAAACCC", end = "AACCCCCC", bank = ["AAAACCCC","AAACCCCC","AACCCCCC"]
35+
36+
**Output:** 3
37+
38+
**Constraints:**
39+
40+
* `start.length == 8`
41+
* `end.length == 8`
42+
* `0 <= bank.length <= 10`
43+
* `bank[i].length == 8`
44+
* `start`, `end`, and `bank[i]` consist of only the characters `['A', 'C', 'G', 'T']`.
45+
46+
## Solution
47+
48+
```typescript
49+
function minMutation(startGene: string, endGene: string, bank: string[]): number {
50+
const isInBank = (set: Set<string>, cur: string): string[] => {
51+
const res: string[] = []
52+
for (const each of set) {
53+
let diff = 0
54+
for (let i = 0; i < each.length; i++) {
55+
if (each[i] !== cur[i]) {
56+
diff++
57+
if (diff > 1) break
58+
}
59+
}
60+
if (diff === 1) {
61+
res.push(each)
62+
}
63+
}
64+
return res
65+
}
66+
const set = new Set(bank)
67+
const queue: string[] = [startGene]
68+
let step = 0
69+
while (queue.length > 0) {
70+
const curSize = queue.length
71+
for (let i = 0; i < curSize; i++) {
72+
const cur = queue.shift()!
73+
if (cur === endGene) {
74+
return step
75+
}
76+
for (const next of isInBank(set, cur)) {
77+
queue.push(next)
78+
set.delete(next)
79+
}
80+
}
81+
step++
82+
}
83+
return -1
84+
}
85+
86+
export { minMutation }
87+
```

0 commit comments

Comments
 (0)
Please sign in to comment.