Skip to content

Commit 26c70fa

Browse files
authored
Merge pull request #1010 from Jeehay28/main
[Jeehay28] WEEK 10
2 parents 5852823 + 203ebfd commit 26c70fa

File tree

5 files changed

+378
-0
lines changed

5 files changed

+378
-0
lines changed

course-schedule/Jeehay28.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @param {number} numCourses
3+
* @param {number[][]} prerequisites
4+
* @return {boolean}
5+
*/
6+
7+
// ✅ Graph DFS (Depth-First Search) approach
8+
// Time Complexity: O(V + E), where V is the number of courses (numCourses) and E is the number of prerequisites (edges).
9+
// Space Complexity: O(V + E), where V is the number of courses and E is the number of prerequisites.
10+
11+
var canFinish = function (numCourses, prerequisites) {
12+
// prerequisites = [
13+
// [1, 0], // Course 1 depends on Course 0
14+
// [2, 1], // Course 2 depends on Course 1
15+
// [3, 1], // Course 3 depends on Course 1
16+
// [3, 2] // Course 3 depends on Course 2
17+
// ];
18+
19+
// graph = {
20+
// 0: [1], // Course 0 is a prerequisite for Course 1
21+
// 1: [2, 3], // Course 1 is a prerequisite for Courses 2 and 3
22+
// 2: [3], // Course 2 is a prerequisite for Course 3
23+
// 3: [] // Course 3 has no prerequisites
24+
// };
25+
26+
// Build the graph
27+
const graph = {};
28+
29+
// for(let i=0; i<numCourses; i++) {
30+
// graph[i] = []
31+
// }
32+
33+
// Fill in the graph with prerequisites
34+
for (const [course, prereq] of prerequisites) {
35+
if (!graph[prereq]) {
36+
graph[prereq] = [];
37+
}
38+
graph[prereq].push(course);
39+
}
40+
41+
const visited = new Array(numCourses).fill(0);
42+
43+
const dfs = (course) => {
44+
if (visited[course] === 1) return false; // cycle detected!
45+
if (visited[course] === 2) return true; // already visited
46+
47+
visited[course] = 1;
48+
49+
// // Visit all the courses that depend on the current course
50+
for (const nextCourse of graph[course] || []) {
51+
if (!dfs(nextCourse)) {
52+
return false; // cycle detected!
53+
}
54+
}
55+
56+
visited[course] = 2; // fully visited and return true
57+
return true;
58+
};
59+
60+
// Check for each course whether it's possible to finish it
61+
for (let i = 0; i < numCourses; i++) {
62+
if (!dfs(i)) {
63+
return false; // cycle detected!
64+
}
65+
}
66+
67+
return true; // no cycles
68+
};
69+

invert-binary-tree/Jeehay28.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* function TreeNode(val, left, right) {
4+
* this.val = (val===undefined ? 0 : val)
5+
* this.left = (left===undefined ? null : left)
6+
* this.right = (right===undefined ? null : right)
7+
* }
8+
*/
9+
/**
10+
* @param {TreeNode} root
11+
* @return {TreeNode}
12+
*/
13+
14+
// ✔️ Recursive Approach
15+
// Time Complexity: O(N), N = Total number of nodes (each node is processed once)
16+
// Space Complexity: O(H), H = Height of the tree (due to recursion stack depth)
17+
18+
var invertTree = function (root) {
19+
if (!root) return null;
20+
21+
[root.left, root.right] = [root.right, root.left];
22+
23+
invertTree(root.left);
24+
invertTree(root.right);
25+
26+
return root;
27+
};
28+
29+
/**
30+
* Definition for a binary tree node.
31+
* function TreeNode(val, left, right) {
32+
* this.val = (val===undefined ? 0 : val)
33+
* this.left = (left===undefined ? null : left)
34+
* this.right = (right===undefined ? null : right)
35+
* }
36+
*/
37+
/**
38+
* @param {TreeNode} root
39+
* @return {TreeNode}
40+
*/
41+
42+
// ✔️ Stack → DFS approach
43+
// Time Complexity: O(N), N = Total number of nodes (each node is processed once)
44+
// Space Complexity: O(H), H = Height of the tree (due to recursion stack depth)
45+
46+
// var invertTree = function (root) {
47+
// let stack = [root];
48+
49+
// while (stack.length > 0) {
50+
// const node = stack.pop();
51+
// if (!node) continue;
52+
53+
// [node.left, node.right] = [node.right, node.left];
54+
// stack.push(node.left);
55+
// stack.push(node.right);
56+
// }
57+
// return root;
58+
// };
59+
60+
61+
/**
62+
* Definition for a binary tree node.
63+
* function TreeNode(val, left, right) {
64+
* this.val = (val===undefined ? 0 : val)
65+
* this.left = (left===undefined ? null : left)
66+
* this.right = (right===undefined ? null : right)
67+
* }
68+
*/
69+
/**
70+
* @param {TreeNode} root
71+
* @return {TreeNode}
72+
*/
73+
74+
// ✔️ Queue → BFS
75+
// Time Complexity: O(N), N = Total number of nodes (each node is processed once)
76+
// Space Complexity: O(W), W = Maximum width of the tree
77+
// var invertTree = function (root) {
78+
// let queue = [root];
79+
80+
// while (queue.length > 0) {
81+
// const node = queue.shift();
82+
// if (!node) continue;
83+
84+
// [node.left, node.right] = [node.right, node.left];
85+
// queue.push(node.left);
86+
// queue.push(node.right);
87+
// }
88+
// return root;
89+
// };
90+
91+

jump-game/Jeehay28.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// 🚀 Greedy approach: much more efficient than the recursive approach
2+
// Time Complexity: O(n)
3+
// Space Complexity: O(1), No extra memory used
4+
5+
/**
6+
* @param {number[]} nums
7+
* @return {boolean}
8+
*/
9+
var canJump = function (nums) {
10+
// ➡️ The farthest position you can reach from any of the previous indices you have already visited.
11+
let farthest = 0;
12+
13+
for (let i = 0; i < nums.length; i++) {
14+
// You cannot reach this position even with your farthest jump value.
15+
if (i > farthest) return false;
16+
17+
// Compare current maximum jump with the previous maximum.
18+
farthest = Math.max(farthest, nums[i] + i);
19+
20+
// Check if you can reach the last index with the current farthest jump.
21+
if (farthest >= nums.length - 1) return true;
22+
}
23+
return false;
24+
};
25+
26+
27+
/**
28+
* @param {number[]} nums
29+
* @return {boolean}
30+
*/
31+
32+
// Time Complexity: O(n)
33+
// Space Complexity: O(n)
34+
var canJump = function (nums) {
35+
let lastIndex = nums.length - 1;
36+
37+
// Initialize memoization array to track visited indices
38+
let memo = new Array(nums.length).fill(undefined);
39+
40+
const dfs = (i) => {
41+
// Base case: if we've reached or surpassed the last index, return true
42+
if (i >= lastIndex) return true;
43+
44+
// If the current index has already been visited, return the stored result
45+
if (memo[i] !== undefined) return memo[i];
46+
47+
// Calculate the farthest position that can be reached from the current index
48+
let maxJump = Math.min(nums[i] + i, lastIndex);
49+
50+
for (let j = i + 1; j <= maxJump; j++) {
51+
if (dfs(j)) {
52+
memo[i] = true;
53+
return true;
54+
}
55+
}
56+
57+
memo[i] = false;
58+
return false;
59+
};
60+
61+
return dfs(0);
62+
};
63+
64+
65+
// 🌀 recursive approach
66+
// ⚠️ Time Complexity: O(2^n) - Exponential due to recursive branching without memoization
67+
// 🔵 Space Complexity: O(n) - Recursive call stack depth
68+
69+
/**
70+
* Check if you can jump to the last index from the first index.
71+
* @param {number[]} nums - Array where nums[i] is the max jump length from position i.
72+
* @return {boolean} True if you can reach the last index, otherwise false.
73+
*/
74+
75+
// var canJump = function (nums) {
76+
// const dfs = (start) => {
77+
// // Base Case: Reached the last index
78+
// if (start === nums.length - 1) {
79+
// return true;
80+
// }
81+
82+
// // Recursive Case: Try all possible jumps
83+
// for (let i = 1; i <= nums[start]; i++) {
84+
// // Example with nums = [2, 3, 1, 1, 4]:
85+
// // start = 1, nums[1] = 3 (can jump 1, 2, or 3 steps)
86+
// // Possible calls:
87+
// // dfs(1 + 1) -> check from index 2
88+
// // dfs(1 + 2) -> check from index 3
89+
// // dfs(1 + 3) -> reached the last index (success)
90+
91+
// if (dfs(start + i)) {
92+
// return true;
93+
// }
94+
// }
95+
96+
// return false; // cannot reach the last index
97+
// };
98+
99+
// return dfs(0);
100+
// };
101+

merge-k-sorted-lists/Jeehay28.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Brute Force (Array Sorting) - Good for smaller cases
2+
// 🕒 Time Complexity: O(N log N), where N is the total number of nodes
3+
// 🗂️ Space Complexity: O(N)
4+
5+
/**
6+
* Definition for singly-linked list.
7+
* function ListNode(val, next) {
8+
* this.val = (val===undefined ? 0 : val)
9+
* this.next = (next===undefined ? null : next)
10+
* }
11+
*/
12+
/**
13+
* @param {ListNode[]} lists
14+
* @return {ListNode}
15+
*/
16+
var mergeKLists = function (lists) {
17+
const nums = [];
18+
19+
// ┌──────────────────────────────────────────────────────────────────┐
20+
// │ Step 1: Extract values from all linked lists │
21+
// │ We traverse each linked list and push node values into 'nums'. │
22+
// │ This flattens the K lists into a single array. │
23+
// └──────────────────────────────────────────────────────────────────┘
24+
for (let list of lists) {
25+
while (list) {
26+
nums.push(list.val);
27+
list = list.next;
28+
}
29+
}
30+
31+
// ┌──────────────────────────────────────────────────────────────────┐
32+
// │ Step 2: Sort the values │
33+
// │ JavaScript's default sort is lexicographical, so we use a custom │
34+
// │ comparator to sort numbers correctly in ascending order. │
35+
// └──────────────────────────────────────────────────────────────────┘
36+
nums.sort((a, b) => a - b);
37+
38+
// ┌──────────────────────────────────────────────────────────────────┐
39+
// │ Step 3: Create a new sorted linked list │
40+
// │ Initialize a dummy node, then iterate through the sorted array. │
41+
// │ For each value, create a new ListNode and append it to the list. │
42+
// └──────────────────────────────────────────────────────────────────┘
43+
let dummy = new ListNode(-1);
44+
let current = dummy;
45+
46+
for (num of nums) {
47+
current.next = new ListNode(num);
48+
current = current.next;
49+
}
50+
51+
// ┌──────────────────────────────────────────────────────────────────┐
52+
// │ Step 4: Return the merged list │
53+
// │ We return dummy.next since dummy is a placeholder. │
54+
// └──────────────────────────────────────────────────────────────────┘
55+
return dummy.next;
56+
};
57+
58+
/**
59+
* ┌──────────────────────────────────────────────────────────────────┐
60+
* │ Time & Space Complexity │
61+
* ├──────────────────────────────────────────────────────────────────┤
62+
* │ Operation │ Complexity │
63+
* ├──────────────────────────────────────────────────────────────────┤
64+
* │ Extracting values │ O(N) - N is the total number of nodes │
65+
* │ Sorting values │ O(N log N) - JavaScript's sort uses Timsort │
66+
* │ Building linked list │ O(N) - Iterates through sorted array │
67+
* ├──────────────────────────────────────────────────────────────────┤
68+
* │ Overall Time Complexity │ O(N log N) │
69+
* ├──────────────────────────────────────────────────────────────────┤
70+
* │ Space Complexity │ O(N) - Storing all node values in array │
71+
* └──────────────────────────────────────────────────────────────────┘
72+
*/
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* @param {number[]} nums
3+
* @param {number} target
4+
* @return {number}
5+
*/
6+
7+
// ✅ Iterative Binary Search for Rotated Sorted Array
8+
// Time Complexity: O(log N)
9+
// Space Complexity: O(1)
10+
var search = function (nums, target) {
11+
let left = 0;
12+
let right = nums.length - 1;
13+
14+
while (left <= right) {
15+
let pointer = Math.floor((left + right) / 2);
16+
17+
if (nums[pointer] === target) {
18+
return pointer;
19+
}
20+
21+
// Check if the left half is sorted
22+
if (nums[left] <= nums[pointer]) {
23+
// Target is in the sorted left half
24+
if (nums[left] <= target && target < nums[pointer]) {
25+
right = pointer - 1;
26+
} else {
27+
// Target is not in the left half, so search in the right half
28+
left = pointer + 1;
29+
}
30+
} else {
31+
// The right half must be sorted
32+
33+
// Target is in the sorted right half
34+
if (nums[pointer] < target && target <= nums[right]) {
35+
left = pointer + 1;
36+
} else {
37+
// Target is not in the right half, so search in the left half
38+
right = pointer - 1;
39+
}
40+
}
41+
}
42+
43+
return -1;
44+
};
45+

0 commit comments

Comments
 (0)