|
|
@@ -0,0 +1,927 @@ |
|
|
Two pointers: one input, opposite ends |
|
|
|
|
|
```python3 |
|
|
def fn(arr): |
|
|
left = ans = 0 |
|
|
right = len(arr) - 1 |
|
|
|
|
|
while left < right: |
|
|
# do some logic here with left and right |
|
|
if CONDITION: |
|
|
left += 1 |
|
|
else: |
|
|
right -= 1 |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = arr => { |
|
|
let left = 0, ans = 0, right = arr.length - 1; |
|
|
|
|
|
while (left < right) { |
|
|
// do some logic here with left and right |
|
|
if (CONDITION) { |
|
|
left++; |
|
|
} else { |
|
|
right--; |
|
|
} |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Two pointers: two inputs, exhaust both |
|
|
|
|
|
```python |
|
|
def fn(arr1, arr2): |
|
|
i = j = ans = 0 |
|
|
|
|
|
while i < len(arr1) and j < len(arr2): |
|
|
# do some logic here |
|
|
if CONDITION: |
|
|
i += 1 |
|
|
else: |
|
|
j += 1 |
|
|
|
|
|
while i < len(arr1): |
|
|
# do logic |
|
|
i += 1 |
|
|
|
|
|
while j < len(arr2): |
|
|
# do logic |
|
|
j += 1 |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = (arr1, arr2) => { |
|
|
let i = 0, j = 0, ans = 0; |
|
|
|
|
|
while (i < arr1.length && j < arr2.length) { |
|
|
// do some logic here |
|
|
if (CONDITION) { |
|
|
i++; |
|
|
} else { |
|
|
j++; |
|
|
} |
|
|
} |
|
|
|
|
|
while (i < arr1.length) { |
|
|
// do logic |
|
|
i++; |
|
|
} |
|
|
|
|
|
while (j < arr2.length) { |
|
|
// do logic |
|
|
j++; |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Sliding window |
|
|
|
|
|
```python3 |
|
|
def fn(arr): |
|
|
left = ans = curr = 0 |
|
|
|
|
|
for right in range(len(arr)): |
|
|
# do logic here to add arr[right] to curr |
|
|
|
|
|
while WINDOW_CONDITION_BROKEN: |
|
|
# remove arr[left] from curr |
|
|
left += 1 |
|
|
|
|
|
# update ans |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = arr => { |
|
|
let left = 0, ans = 0, curr = 0; |
|
|
|
|
|
for (let right = 0; right < arr.length; right++) { |
|
|
// do logic here to add arr[right] to curr |
|
|
|
|
|
while (WINDOW_CONDITION_BROKEN) { |
|
|
// remove arr[left] from curr |
|
|
left++; |
|
|
} |
|
|
|
|
|
// update ans |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Build a prefix sum |
|
|
|
|
|
```python3 |
|
|
def fn(arr): |
|
|
prefix = [arr[0]] |
|
|
for i in range(1, len(arr)): |
|
|
prefix.append(prefix[-1] + arr[i]) |
|
|
|
|
|
return prefix |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = arr => { |
|
|
let prefix = [arr[0]]; |
|
|
for (let i = 1; i < arr.length; i++) { |
|
|
prefix.push(prefix[prefix.length - 1] + arr[i]); |
|
|
} |
|
|
|
|
|
return prefix; |
|
|
} |
|
|
``` |
|
|
|
|
|
Efficient string building |
|
|
|
|
|
```python3 |
|
|
# arr is a list of characters |
|
|
def fn(arr): |
|
|
ans = [] |
|
|
for c in arr: |
|
|
ans.append(c) |
|
|
|
|
|
return "".join(ans) |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
// arr is a list of characters |
|
|
let fn = arr => { |
|
|
let ans = []; |
|
|
for (const c of arr) { |
|
|
ans.push(c); |
|
|
} |
|
|
|
|
|
return ans.join("") |
|
|
} |
|
|
|
|
|
let fn = arr => { |
|
|
let ans = ""; |
|
|
for (const c of arr) { |
|
|
ans += c; |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
> In JavaScript, benchmarking shows that concatenation with += is faster than using .join(). |
|
|
|
|
|
Linked list: fast and slow pointer |
|
|
|
|
|
```python3 |
|
|
def fn(head): |
|
|
slow = head |
|
|
fast = head |
|
|
ans = 0 |
|
|
|
|
|
while fast and fast.next: |
|
|
# do logic |
|
|
slow = slow.next |
|
|
fast = fast.next.next |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = head => { |
|
|
let slow = head; |
|
|
let fast = head; |
|
|
let ans = 0; |
|
|
|
|
|
while (fast && fast.next) { |
|
|
// do logic |
|
|
slow = slow.next; |
|
|
fast = fast.next.next; |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Reversing a linked list |
|
|
|
|
|
```python3 |
|
|
def fn(head): |
|
|
curr = head |
|
|
prev = None |
|
|
while curr: |
|
|
next_node = curr.next |
|
|
curr.next = prev |
|
|
prev = curr |
|
|
curr = next_node |
|
|
|
|
|
return prev |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = head => { |
|
|
let curr = head; |
|
|
let prev = null; |
|
|
while (curr) { |
|
|
let nextNode = curr.next; |
|
|
curr.next = prev; |
|
|
prev = curr; |
|
|
curr = nextNode; |
|
|
} |
|
|
|
|
|
return prev; |
|
|
} |
|
|
``` |
|
|
|
|
|
Find number of subarrays that fit an exact criteria |
|
|
|
|
|
```python3 |
|
|
from collections import defaultdict |
|
|
|
|
|
def fn(arr, k): |
|
|
counts = defaultdict(int) |
|
|
counts[0] = 1 |
|
|
ans = curr = 0 |
|
|
|
|
|
for num in arr: |
|
|
# do logic to change curr |
|
|
ans += counts[curr - k] |
|
|
counts[curr] += 1 |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = (arr, k) => { |
|
|
let counts = new Map(); |
|
|
counts.set(0, 1); |
|
|
let ans = 0, curr = 0; |
|
|
|
|
|
for (const num of arr) { |
|
|
// do logic to change curr |
|
|
ans += counts.get(curr - k) || 0; |
|
|
counts.set(curr, (counts.get(curr) || 0) + 1); |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Monotonic increasing stack |
|
|
|
|
|
The same logic can be applied to maintain a monotonic queue. |
|
|
|
|
|
```python3 |
|
|
def fn(arr): |
|
|
stack = [] |
|
|
ans = 0 |
|
|
|
|
|
for num in arr: |
|
|
# for monotonic decreasing, just flip the > to < |
|
|
while stack and stack[-1] > num: |
|
|
# do logic |
|
|
stack.pop() |
|
|
stack.append(num) |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = arr => { |
|
|
let stack = []; |
|
|
let ans = 0; |
|
|
|
|
|
for (const num of arr) { |
|
|
// for monotonic decreasing, just flip the > to < |
|
|
while (stack.length && stack[stack.length - 1] > num) { |
|
|
// do logic |
|
|
stack.pop(); |
|
|
} |
|
|
|
|
|
stack.push(num); |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Binary tree: DFS (recursive) |
|
|
|
|
|
```python3 |
|
|
def dfs(root): |
|
|
if not root: |
|
|
return |
|
|
|
|
|
ans = 0 |
|
|
|
|
|
# do logic |
|
|
dfs(root.left) |
|
|
dfs(root.right) |
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let dfs = root => { |
|
|
if (!root) { |
|
|
return; |
|
|
} |
|
|
|
|
|
let ans = 0; |
|
|
|
|
|
// do logic |
|
|
dfs(root.left); |
|
|
dfs(root.right); |
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Binary tree: DFS (iterative) |
|
|
|
|
|
```python3 |
|
|
def dfs(root): |
|
|
stack = [root] |
|
|
ans = 0 |
|
|
|
|
|
while stack: |
|
|
node = stack.pop() |
|
|
# do logic |
|
|
if node.left: |
|
|
stack.append(node.left) |
|
|
if node.right: |
|
|
stack.append(node.right) |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let dfs = root => { |
|
|
let stack = [root]; |
|
|
let ans = 0; |
|
|
|
|
|
while (stack.length) { |
|
|
let node = stack.pop(); |
|
|
// do logic |
|
|
if (node.left) { |
|
|
stack.push(node.left); |
|
|
} |
|
|
if (node.right) { |
|
|
stack.push(node.right); |
|
|
} |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Binary tree: BFS |
|
|
|
|
|
```python3 |
|
|
from collections import deque |
|
|
|
|
|
def fn(root): |
|
|
queue = deque([root]) |
|
|
ans = 0 |
|
|
|
|
|
while queue: |
|
|
current_length = len(queue) |
|
|
# do logic for current level |
|
|
|
|
|
for _ in range(current_length): |
|
|
node = queue.popleft() |
|
|
# do logic |
|
|
if node.left: |
|
|
queue.append(node.left) |
|
|
if node.right: |
|
|
queue.append(node.right) |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = root => { |
|
|
let queue = [root]; |
|
|
let ans = 0; |
|
|
|
|
|
while (queue.length) { |
|
|
let currentLength = queue.length; |
|
|
// do logic for current level |
|
|
|
|
|
let nextQueue = []; |
|
|
|
|
|
for (let i = 0; i < currentLength; i++) { |
|
|
let node = queue[i]; |
|
|
// do logic |
|
|
if (node.left) { |
|
|
nextQueue.push(node.left); |
|
|
} |
|
|
if (node.right) { |
|
|
nextQueue.push(node.right); |
|
|
} |
|
|
} |
|
|
|
|
|
queue = nextQueue; |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Graph: DFS (recursive) |
|
|
|
|
|
For the graph templates, assume the nodes are numbered from 0 to n - 1 and the graph is given as an adjacency list. Depending on the problem, you may need to convert the input into an equivalent adjacency list before using the templates. |
|
|
|
|
|
```python3 |
|
|
def fn(graph): |
|
|
def dfs(node): |
|
|
ans = 0 |
|
|
# do some logic |
|
|
for neighbor in graph[node]: |
|
|
if neighbor not in seen: |
|
|
seen.add(neighbor) |
|
|
ans += dfs(neighbor) |
|
|
|
|
|
return ans |
|
|
|
|
|
seen = {START_NODE} |
|
|
return dfs(START_NODE) |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = graph => { |
|
|
let dfs = node => { |
|
|
let ans = 0; |
|
|
// do some logic |
|
|
for (const neighbor of graph[node]) { |
|
|
if (!seen.has(neighbor)) { |
|
|
seen.add(neighbor); |
|
|
ans += dfs(neighbor); |
|
|
} |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
|
|
|
let seen = new Set([START_NODE]); |
|
|
return dfs(START_NODE); |
|
|
} |
|
|
``` |
|
|
|
|
|
Graph: DFS (iterative) |
|
|
|
|
|
```python3 |
|
|
def fn(graph): |
|
|
stack = [START_NODE] |
|
|
seen = {START_NODE} |
|
|
ans = 0 |
|
|
|
|
|
while stack: |
|
|
node = stack.pop() |
|
|
# do some logic |
|
|
for neighbor in graph[node]: |
|
|
if neighbor not in seen: |
|
|
seen.add(neighbor) |
|
|
stack.append(neighbor) |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = graph => { |
|
|
let stack = [START_NODE]; |
|
|
let seen = new Set([START_NODE]); |
|
|
let ans = 0; |
|
|
|
|
|
while (stack.length) { |
|
|
let node = stack.pop(); |
|
|
// do some logic |
|
|
for (const neighbor of graph[node]) { |
|
|
if (!seen.has(neighbor)) { |
|
|
seen.add(neighbor); |
|
|
stack.push(neighbor); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
```python3 |
|
|
from collections import deque |
|
|
|
|
|
def fn(graph): |
|
|
queue = deque([START_NODE]) |
|
|
seen = {START_NODE} |
|
|
ans = 0 |
|
|
|
|
|
while queue: |
|
|
node = queue.popleft() |
|
|
# do some logic |
|
|
for neighbor in graph[node]: |
|
|
if neighbor not in seen: |
|
|
seen.add(neighbor) |
|
|
queue.append(neighbor) |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = graph => { |
|
|
let queue = [START_NODE]; |
|
|
let seen = new Set([START_NODE]); |
|
|
let ans = 0; |
|
|
|
|
|
while (queue.length) { |
|
|
let currentLength = 0; |
|
|
let nextQueue = []; |
|
|
|
|
|
for (let i = 0; i < currentLength; i++) { |
|
|
let node = queue[i]; |
|
|
// do some logic |
|
|
for (const neighbor of graph[node]) { |
|
|
if (!seen.has(neighbor)) { |
|
|
seen.add(neighbor); |
|
|
nextQueue.push(neighbor); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
queue = nextQueue; |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Find top k elements with heap |
|
|
|
|
|
```python |
|
|
import heapq |
|
|
|
|
|
def fn(arr, k): |
|
|
heap = [] |
|
|
for num in arr: |
|
|
# do some logic to push onto heap according to problem's criteria |
|
|
heapq.heappush(heap, (CRITERIA, num)) |
|
|
if len(heap) > k: |
|
|
heapq.heappop(heap) |
|
|
|
|
|
return [num for num in heap] |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
/* |
|
|
JavaScript does not have any built in support - it is recommended |
|
|
that you have another language ready in case you need to use a heap |
|
|
*/ |
|
|
``` |
|
|
|
|
|
soy |
|
|
|
|
|
Binary search |
|
|
|
|
|
```python3 |
|
|
def fn(arr, target): |
|
|
left = 0 |
|
|
right = len(arr) - 1 |
|
|
while left <= right: |
|
|
mid = (left + right) // 2 |
|
|
if arr[mid] == target: |
|
|
# do something |
|
|
return |
|
|
if arr[mid] > target: |
|
|
right = mid - 1 |
|
|
else: |
|
|
left = mid + 1 |
|
|
|
|
|
# left is the insertion point |
|
|
return left |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = (arr, target) => { |
|
|
let left = 0; |
|
|
let right = arr.length - 1; |
|
|
while (left <= right) { |
|
|
let mid = Math.floor((left + right) / 2); |
|
|
if (arr[mid] == target) { |
|
|
// do something |
|
|
return; |
|
|
} |
|
|
if (arr[mid] > target) { |
|
|
right = mid - 1; |
|
|
} else { |
|
|
left = mid + 1; |
|
|
} |
|
|
} |
|
|
|
|
|
// left is the insertion point |
|
|
return left; |
|
|
} |
|
|
``` |
|
|
|
|
|
Binary search: duplicate elements, left-most insertion point |
|
|
|
|
|
```python |
|
|
def fn(arr, target): |
|
|
left = 0 |
|
|
right = len(arr) |
|
|
while left < right: |
|
|
mid = (left + right) // 2 |
|
|
if arr[mid] >= target: |
|
|
right = mid |
|
|
else: |
|
|
left = mid + 1 |
|
|
|
|
|
return left |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = (arr, target) => { |
|
|
let left = 0; |
|
|
let right = arr.length; |
|
|
while (left < right) { |
|
|
let mid = Math.floor((left + right) / 2); |
|
|
if (arr[mid] >= target) { |
|
|
right = mid; |
|
|
} else { |
|
|
left = mid + 1; |
|
|
} |
|
|
} |
|
|
|
|
|
return left; |
|
|
} |
|
|
``` |
|
|
|
|
|
Binary search: duplicate elements, right-most insertion point |
|
|
|
|
|
```python |
|
|
def fn(arr, target): |
|
|
left = 0 |
|
|
right = len(arr) |
|
|
while left < right: |
|
|
mid = (left + right) // 2 |
|
|
if arr[mid] > target: |
|
|
right = mid |
|
|
else: |
|
|
left = mid + 1 |
|
|
|
|
|
return left |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = (arr, target) => { |
|
|
let left = 0; |
|
|
let right = arr.length; |
|
|
while (left < right) { |
|
|
let mid = Math.floor((left + right) / 2); |
|
|
if (arr[mid] > target) { |
|
|
right = mid; |
|
|
} else { |
|
|
left = mid + 1; |
|
|
} |
|
|
} |
|
|
|
|
|
return left; |
|
|
} |
|
|
``` |
|
|
|
|
|
Binary search: for greedy problems |
|
|
|
|
|
If looking for a minimum: |
|
|
|
|
|
```python |
|
|
def fn(arr): |
|
|
def check(x): |
|
|
# this function is implemented depending on the problem |
|
|
return BOOLEAN |
|
|
|
|
|
left = MINIMUM_POSSIBLE_ANSWER |
|
|
right = MAXIMUM_POSSIBLE_ANSWER |
|
|
while left <= right: |
|
|
mid = (left + right) // 2 |
|
|
if check(mid): |
|
|
right = mid - 1 |
|
|
else: |
|
|
left = mid + 1 |
|
|
|
|
|
return left |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = arr => { |
|
|
let check = x => { |
|
|
// this function is implemented depending on the problem |
|
|
return BOOLEAN; |
|
|
} |
|
|
|
|
|
let left = MINIMUM_POSSIBLE_ANSWER; |
|
|
let right = MAXMIMUM_POSSIBLE_ANSWER; |
|
|
while (left <= right) { |
|
|
let mid = Math.floor((left + right) / 2); |
|
|
if (check(mid)) { |
|
|
right = mid - 1; |
|
|
} else { |
|
|
left = mid + 1; |
|
|
} |
|
|
} |
|
|
|
|
|
return left; |
|
|
} |
|
|
``` |
|
|
|
|
|
If looking for a maximum: |
|
|
|
|
|
```python |
|
|
def fn(arr): |
|
|
def check(x): |
|
|
# this function is implemented depending on the problem |
|
|
return BOOLEAN |
|
|
|
|
|
left = MINIMUM_POSSIBLE_ANSWER |
|
|
right = MAXIMUM_POSSIBLE_ANSWER |
|
|
while left <= right: |
|
|
mid = (left + right) // 2 |
|
|
if check(mid): |
|
|
left = mid + 1 |
|
|
else: |
|
|
right = mid - 1 |
|
|
|
|
|
return right |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = arr => { |
|
|
let check = x => { |
|
|
// this function is implemented depending on the problem |
|
|
return BOOLEAN; |
|
|
} |
|
|
|
|
|
let left = MINIMUM_POSSIBLE_ANSWER; |
|
|
let right = MAXMIMUM_POSSIBLE_ANSWER; |
|
|
while (left <= right) { |
|
|
let mid = Math.floor((left + right) / 2); |
|
|
if (check(mid)) { |
|
|
left = mid + 1; |
|
|
} else { |
|
|
right = mid - 1; |
|
|
} |
|
|
} |
|
|
|
|
|
return right; |
|
|
} |
|
|
``` |
|
|
|
|
|
Backtracking |
|
|
|
|
|
```python |
|
|
def backtrack(curr, OTHER_ARGUMENTS...): |
|
|
if (BASE_CASE): |
|
|
# modify the answer |
|
|
return |
|
|
|
|
|
ans = 0 |
|
|
for (ITERATE_OVER_INPUT): |
|
|
# modify the current state |
|
|
ans += backtrack(curr, OTHER_ARGUMENTS...) |
|
|
# undo the modification of the current state |
|
|
|
|
|
return ans |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let backtrack = (curr, OTHER_ARGUMENTS...) => { |
|
|
if (BASE_CASE) { |
|
|
// modify the answer |
|
|
return; |
|
|
} |
|
|
|
|
|
let ans = 0; |
|
|
for (ITERATE_OVER_INPUT) { |
|
|
// modify the current state |
|
|
ans += backtrack(curr, OTHER_ARGUMENTS...); |
|
|
// undo the modification of the current state |
|
|
} |
|
|
|
|
|
return ans; |
|
|
} |
|
|
``` |
|
|
|
|
|
Dynamic programming: top-down memoization |
|
|
|
|
|
```python |
|
|
def fn(arr): |
|
|
def dp(STATE): |
|
|
if BASE_CASE: |
|
|
return 0 |
|
|
|
|
|
if STATE in memo: |
|
|
return memo[STATE] |
|
|
|
|
|
ans = RECURRENCE_RELATION(STATE) |
|
|
memo[STATE] = ans |
|
|
return ans |
|
|
|
|
|
memo = {} |
|
|
return dp(STATE_FOR_WHOLE_INPUT) |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
let fn = arr => { |
|
|
let dp = STATE => { |
|
|
if (BASE_CASE) { |
|
|
return 0; |
|
|
} |
|
|
|
|
|
if (memo[STATE] != -1) { |
|
|
return memo[STATE]; |
|
|
} |
|
|
|
|
|
let ans = RECURRENCE_RELATION(STATE); |
|
|
memo[STATE] = ans; |
|
|
return ans; |
|
|
} |
|
|
|
|
|
let memo = ARRAY_SIZED_ACCORDING_TO_STATE; |
|
|
return dp(STATE_FOR_WHOLE_INPUT); |
|
|
} |
|
|
``` |
|
|
|
|
|
Build a trie |
|
|
|
|
|
```python3 |
|
|
# note: using a class is only necessary if you want to store data at each node. |
|
|
# otherwise, you can implement a trie using only hash maps. |
|
|
class TrieNode: |
|
|
def __init__(self): |
|
|
# you can store data at nodes if you wish |
|
|
self.data = None |
|
|
self.children = {} |
|
|
|
|
|
def fn(words): |
|
|
root = TrieNode() |
|
|
for word in words: |
|
|
curr = root |
|
|
for c in word: |
|
|
if c not in curr.children: |
|
|
curr.children[c] = TrieNode() |
|
|
curr = curr.children[c] |
|
|
# at this point, you have a full word at curr |
|
|
# you can perform more logic here to give curr an attribute if you want |
|
|
|
|
|
return root |
|
|
``` |
|
|
|
|
|
```javascript |
|
|
// note: using a class is only necessary if you want to store data at each node. |
|
|
// otherwise, you can implement a trie using only hash maps. |
|
|
class TrieNode { |
|
|
constructor() { |
|
|
// you can store data at nodes if you wish |
|
|
this.data = null; |
|
|
this.children = new Map(); |
|
|
} |
|
|
} |
|
|
|
|
|
let fn = words => { |
|
|
let root = new TrieNode(); |
|
|
for (const word of words) { |
|
|
let curr = root; |
|
|
for (const c of word) { |
|
|
if (!curr.children.has(c)) { |
|
|
curr.children.set(c, new TrieNode()); |
|
|
} |
|
|
curr = curr.children.get(c); |
|
|
} |
|
|
|
|
|
// at this point, you have a full word at curr |
|
|
// you can perform more logic here to give curr an attribute if you want |
|
|
} |
|
|
|
|
|
return root; |
|
|
} |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|