Skip to content

Commit 62c7955

Browse files
committed
Add solutions week 9
1 parent 151ec8c commit 62c7955

File tree

3 files changed

+180
-0
lines changed

3 files changed

+180
-0
lines changed

clone-graph/bhyun-kim.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""
2+
133. Clone Graph
3+
https://leetcode.com/problems/clone-graph/
4+
5+
Solution:
6+
To clone a graph, we can use a depth-first search (DFS) to explore all nodes and their neighbors.
7+
We can create a helper function that takes a node and returns its clone.
8+
9+
- We can use a dictionary to map old nodes to new nodes.
10+
- We can create a helper function to clone a node and its neighbors.
11+
- If the node has already been cloned, we return the clone.
12+
- Otherwise, we create a new clone and add it to the dictionary.
13+
- We clone all neighbors of the node recursively.
14+
- We return the clone.
15+
- We start the DFS from the given node and return the clone.
16+
17+
Time complexity: O(n+m)
18+
- n is the number of nodes in the graph.
19+
- m is the number of edges in the graph.
20+
- We explore all nodes and edges once.
21+
22+
Space complexity: O(n)
23+
- We use a dictionary to keep track of the mapping between old nodes and new nodes.
24+
- The maximum depth of the recursive call stack is the number of nodes in the graph.
25+
"""
26+
27+
# Definition for a Node.
28+
class Node:
29+
def __init__(self, val = 0, neighbors = None):
30+
self.val = val
31+
self.neighbors = neighbors if neighbors is not None else []
32+
33+
from typing import Optional
34+
35+
class Solution:
36+
def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
37+
if not node:
38+
return None
39+
40+
old_to_new = {}
41+
42+
def dfs(node):
43+
if node in old_to_new:
44+
return old_to_new[node]
45+
46+
clone = Node(node.val)
47+
old_to_new[node] = clone
48+
49+
for neighbor in node.neighbors:
50+
clone.neighbors.append(dfs(neighbor))
51+
52+
return clone
53+
54+
return dfs(node)

course-schedule/bhyun-kim.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""
2+
207. Course Schedule
3+
https://leetcode.com/problems/course-schedule/
4+
5+
Solution:
6+
If there is a cycle in the graph, it is impossible to finish all courses.
7+
We can detect a cycle by using DFS and keeping track of the state of each node.
8+
9+
- We can create an adjacency list to represent the graph.
10+
- We can use a state array to keep track of the state of each node.
11+
- 0: unvisited, 1: visiting, 2: visited
12+
- We can create a helper function to check if there is a cycle starting from a node.
13+
- If the node is being visited, we have a cycle.
14+
- If the node has been visited, there is no cycle.
15+
- If not, we mark the node as visiting and explore its neighbors.
16+
- After exploring all neighbors, we mark the node as visited.
17+
- We can iterate through all nodes and check for cycles.
18+
- If we find a cycle, we return False.
19+
- If no cycle is found, we return True.
20+
21+
Time complexity: O(m + n)
22+
- m is the number of prerequisites.
23+
- n is the number of courses.
24+
- We explore all prerequisites and courses once.
25+
26+
Space complexity: O(m + n)
27+
- We use an adjacency list to represent the graph.
28+
- We use a state array to keep track of the state of each node.
29+
"""
30+
31+
from collections import defaultdict
32+
from typing import List
33+
34+
class Solution:
35+
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
36+
adj_list = defaultdict(list)
37+
for dest, src in prerequisites:
38+
adj_list[src].append(dest)
39+
40+
# State: 0 = unvisited, 1 = visiting, 2 = visited
41+
state = [0] * numCourses
42+
43+
def has_cycle(v):
44+
if state[v] == 1: # Node is being visited, so we have a cycle
45+
return True
46+
if state[v] == 2: # Node has been visited, no cycle here
47+
return False
48+
49+
state[v] = 1
50+
for neighbor in adj_list[v]:
51+
if has_cycle(neighbor):
52+
return True
53+
54+
state[v] = 2
55+
return False
56+
57+
for course in range(numCourses):
58+
if state[course] == 0:
59+
if has_cycle(course):
60+
return False
61+
62+
return True
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
211. Design Add and Search Words Data Structure
3+
https://leetcode.com/problems/design-add-and-search-words-data-structure/
4+
5+
Solution:
6+
To solve this problem, we can use a trie data structure to store the words.
7+
We can create a TrieNode class to represent each node in the trie.
8+
9+
In addWord, we can iterate through each character in the word and create nodes as needed.
10+
We mark the end of the word by setting is_end_of_word to True.
11+
12+
In search, we can use a depth-first search (DFS) to explore all possible paths.
13+
If we encounter a '.', we explore all children of the current node.
14+
If we find a mismatch or reach the end of the word, we return False.
15+
16+
17+
Time complexity:
18+
- addWord: O(m)
19+
- m is the length of the word.
20+
- We iterate through each character in the word once.
21+
- search: O(n * 26^l)
22+
- n is the number of nodes in the trie.
23+
- l is the length of the word.
24+
- We explore all possible paths in the trie.
25+
- The worst-case time complexity is O(n * 26^l) when all nodes have 26 children.
26+
27+
Space complexity: O(n)
28+
- n is the number of nodes in the trie.
29+
- We use a trie data structure to store the words.
30+
"""
31+
32+
class TrieNode:
33+
def __init__(self):
34+
self.children = {}
35+
self.is_end_of_word = False
36+
37+
class WordDictionary:
38+
def __init__(self):
39+
self.root = TrieNode()
40+
41+
def addWord(self, word):
42+
node = self.root
43+
for char in word:
44+
if char not in node.children:
45+
node.children[char] = TrieNode()
46+
node = node.children[char]
47+
node.is_end_of_word = True
48+
49+
def search(self, word):
50+
def dfs(j, node):
51+
for i in range(j, len(word)):
52+
char = word[i]
53+
if char == '.':
54+
for child in node.children.values():
55+
if dfs(i + 1, child):
56+
return True
57+
return False
58+
else:
59+
if char not in node.children:
60+
return False
61+
node = node.children[char]
62+
return node.is_end_of_word
63+
64+
return dfs(0, self.root)

0 commit comments

Comments
 (0)