Skip to content

[Helena] Week 9 solutions #152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions clone-graph/yolophg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Time Complexity: O(N + E) N = Node + E = Edge
// Space Complexity: O(N + E)

var cloneGraph = function (node) {
// to keep track of all the nodes that have already been copied
const map = new Map();

// helper to perform the deep copy
const dfs = (currentNode) => {
if (!currentNode) return null;

// if the node has already been copied, return the copied one
if (map.has(currentNode)) return map.get(currentNode);

// create a new node with the current node's value
const newNode = new Node(currentNode.val);

// store this new node in the map
map.set(currentNode, newNode);

// iterate through each neighbor of the current node
for (const neighbor of currentNode.neighbors) {
// clone the neighbors and add them to the new node's neighbors
newNode.neighbors.push(dfs(neighbor));
}

// return the newly created node
return newNode;
};

// start the deep copy from the given node
return dfs(node);
};
27 changes: 27 additions & 0 deletions combination-sum/yolophg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Time Complexity: O(n * target * k)
// Space Complexity: O(target)

var combinationSum = function (candidates, target) {
// initialize dp array to store combinations
const dp = Array(target + 1)
.fill(null)
.map(() => []);

// sort candidates to ensure uniqueness and optimize processing
candidates.sort((a, b) => a - b);

// one way to make sum 0 (by choosing no elements)
dp[0] = [[]];

// iterate through each candidate
for (let num of candidates) {
// update dp array for current candidate
for (let i = num; i <= target; i++) {
for (let combination of dp[i - num]) {
dp[i].push([...combination, num]);
}
}
}

return dp[target];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Time Complexity: O(n)
// Space Complexity: O(n)

var buildTree = function (preorder, inorder) {
// build a map for quick lookup of index positions in inorder array
// map to store the value -> index relationships
let map = new Map();
inorder.forEach((value, index) => map.set(value, index));

// recursive function to construct the binary tree
function buildTreeHelper(preStart, preEnd, inStart, inEnd) {
// if there are no elements to consider
if (preStart > preEnd || inStart > inEnd) return null;

// the first element in preorder is the root of the current tree
let rootValue = preorder[preStart];
// create a new root node
let root = { val: rootValue, left: null, right: null };

// find the root in the inorder array to split the tree
let inRootIndex = map.get(rootValue);
// number of nodes in the left subtree
let numsLeft = inRootIndex - inStart;

// recursively build the left subtree
root.left = buildTreeHelper(
preStart + 1,
preStart + numsLeft,
inStart,
inRootIndex - 1
);

// recursively build the right subtree
root.right = buildTreeHelper(
preStart + numsLeft + 1,
preEnd,
inRootIndex + 1,
inEnd
);

return root;
}

// initiate the recursive construction
return buildTreeHelper(0, preorder.length - 1, 0, inorder.length - 1);
};
47 changes: 47 additions & 0 deletions course-schedule/yolophg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Time Complexity: O(numCourses * E) E = Edge
// Space Complexity: O(numCourses * E)

// initialize an array to keep track of the in-degrees for each course
let inDegree = new Array(numCourses).fill(0);
// initialize an adjacency list to represent the graph of courses
let adjList = new Array(numCourses).fill(0).map(() => []);

// fill the in-degree array and adjacency list based on the prerequisites
for (let [course, prereq] of prerequisites) {
// increment the in-degree of the course
inDegree[course]++;
// add the course to the adjacency list of the prerequisite
adjList[prereq].push(course);
}

// initialize a queue to keep track of courses with no prerequisites (in-degree of 0)
let queue = [];
for (let i = 0; i < numCourses; i++) {
if (inDegree[i] === 0) {
queue.push(i);
}
}

// initialize a counter to keep track of the number of courses that have been processed
let count = 0;

// process the courses with no prerequisites
while (queue.length > 0) {
// get a course from the queue
let current = queue.shift();
// increment the counter as this course can be taken
count++;

// iterate through the adjacency list of the current course
for (let neighbor of adjList[current]) {
// decrement the in-degree of the neighboring course
inDegree[neighbor]--;
// if in-degree becomes 0, add it to the queue
if (inDegree[neighbor] === 0) {
queue.push(neighbor);
}
}
}

// if the count of processed courses equals the total number of courses, return true
return count === numCourses;
56 changes: 56 additions & 0 deletions design-add-and-search-words-data-structure/yoloophg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// AddWord Method : Time Complexity: O(L)/Space Complexity: O(L) L = the length of the word being added
// Search Method : Time Complexity: O(M)/Space Complexity: O(1) M = the length of the word being searched
// SearchInNode Method : Time Complexity: O(M)/Space Complexity: O(1)

var WordDictionary = function () {
this.root = {};
};

WordDictionary.prototype.addWord = function (word) {
// start from the root node
let node = this.root;
for (let char of word) {
if (!node[char]) {
// if the character does not exist, create a new node
node[char] = {};
}
// move to the next node
node = node[char];
}
// mark the end of the word
node.isEndOfWord = true;
};

WordDictionary.prototype.search = function (word) {
// start searching from the root
return this.searchInNode(word, 0, this.root);
};

WordDictionary.prototype.searchInNode = function (word, index, node) {
if (index === word.length) {
// if all characters are checked
return node.isEndOfWord === true;
}

const char = word[index];
if (char === ".") {
//iIf the character is '.', check all possible nodes at this part
for (let key in node) {
if (
key !== "isEndOfWord" &&
this.searchInNode(word, index + 1, node[key])
) {
// if any path matches, return true
return true;
}
}
// no path matched
return false;
} else if (node[char]) {
// if the character exists in the trie
return this.searchInNode(word, index + 1, node[char]);
} else {
// character path does not exist
return false;
}
};
52 changes: 52 additions & 0 deletions implement-trie-prefix-tree/yolophg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Insert Method : Time Complexity: O(m)/Space Complexity: O(m)
// Search Method : Time Complexity: O(m)/Space Complexity: O(1)
// Starts With Method : Time Complexity: O(p)/Space Complexity: O(1)

var Trie = function () {
this.trie = {};
};

// insert a word into the Trie
Trie.prototype.insert = function (word) {
let node = this.trie;
for (let char of word) {
if (!node[char]) {
// create a new node if it doesn't exist
node[char] = {};
}
// move to the next node
node = node[char];
}
// mark the end of the word
node.isEnd = true;
};

// search for a word in the Trie
Trie.prototype.search = function (word) {
let node = this.trie;
for (let char of word) {
if (!node[char]) {
// character not found
return false;
}
// move to the next node
node = node[char];
}
// Ccheck if it's the end of a valid word
return node.isEnd === true;
};

// check if there's any word in the Trie that starts with the given prefix
Trie.prototype.startsWith = function (prefix) {
let node = this.trie;
for (let char of prefix) {
if (!node[char]) {
// prefix not found
return false;
}
// move to the next node
node = node[char];
}
// prefix found
return true;
};
31 changes: 31 additions & 0 deletions kth-smallest-element-in-a-bst/yolophg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Time Complexity: O(n)
// Space Complexity: O(n)

var kthSmallest = function (root, k) {
let stack = [];
let current = root;
let count = 0;

while (stack.length > 0 || current !== null) {
// go to the leftmost node
while (current !== null) {
stack.push(current);
current = current.left;
}

// pop the node from the stack
current = stack.pop();
count++;

// if reached the kth node
if (count === k) {
return current.val;
}

// go to the right node
current = current.right;
}

// if k is out of the range of the number of in the tree
return null;
};
51 changes: 51 additions & 0 deletions number-of-islands/yolophg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Time Complexity: O(m * n) m = rows n = cols
// Space Complexity: O(m * n)

var numIslands = function (grid) {
const m = grid.length;
const n = grid[0].length;
let numIslands = 0;

// directions arrays for moving up, down, left, and right
const directions = [
[-1, 0],
[1, 0],
[0, -1],
[0, 1],
];

// BFS function
function bfs(row, col) {
const queue = [[row, col]];
// mark as visited
grid[row][col] = "0";

while (queue.length > 0) {
const [r, c] = queue.shift();

for (const [dr, dc] of directions) {
const nr = r + dr;
const nc = c + dc;

if (nr >= 0 && nr < m && nc >= 0 && nc < n && grid[nr][nc] === "1") {
// mark as visited
grid[nr][nc] = "0";
queue.push([nr, nc]);
}
}
}
}

// iterate through each cell in the grid
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (grid[i][j] === "1") {
numIslands++;
// start BFS to mark all connected land cells
bfs(i, j);
}
}
}

return numIslands;
};
Loading