diff --git a/clone-graph/samthekorean.py b/clone-graph/samthekorean.py new file mode 100644 index 000000000..f5ff17eb4 --- /dev/null +++ b/clone-graph/samthekorean.py @@ -0,0 +1,31 @@ +# TC : O(n) +# SC : O(n) +class Solution: + def cloneGraph(self, node: Optional["Node"]) -> Optional["Node"]: + if not node: + return None + + # Dictionary to store cloned nodes + cloned_nodes = {} + # BFS queue starting with the original node + queue = deque([node]) + + # Clone the original node + cloned_node = Node(node.val) + cloned_nodes[node] = cloned_node + + while queue: + current_node = queue.popleft() + + # Iterate through neighbors of the current node + for neighbor in current_node.neighbors: + if neighbor not in cloned_nodes: + # Clone the neighbor and add it to the queue + cloned_neighbor = Node(neighbor.val) + cloned_nodes[neighbor] = cloned_neighbor + queue.append(neighbor) + + # Add the cloned neighbor to the cloned current node's neighbors list + cloned_nodes[current_node].neighbors.append(cloned_nodes[neighbor]) + + return cloned_node diff --git a/course-schedule/samthekorean.py b/course-schedule/samthekorean.py new file mode 100644 index 000000000..45a7fc381 --- /dev/null +++ b/course-schedule/samthekorean.py @@ -0,0 +1,34 @@ +# V is number of verticles and E is number of edges +# TC : O(V+E) +# SC : O(V+E) +class Solution: + def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: + + pre = defaultdict(list) + + for course, p in prerequisites: + pre[course].append(p) + + taken = set() + + def dfs(course): + if not pre[course]: + return True + + if course in taken: + return False + + taken.add(course) + + for p in pre[course]: + if not dfs(p): + return False + + pre[course] = [] + return True + + for course in range(numCourses): + if not dfs(course): + return False + + return True diff --git a/design-add-and-search-words-data-structure/samthekorean.py b/design-add-and-search-words-data-structure/samthekorean.py new file mode 100644 index 000000000..3c230c65e --- /dev/null +++ b/design-add-and-search-words-data-structure/samthekorean.py @@ -0,0 +1,49 @@ +# n: number of words | m: length of the word +# TC: O(n*m) +# SC: O(n*m) + + +class TrieNode: + def __init__(self): + self.children = {} # Dictionary to store child TrieNodes + self.is_word = False # Flag to indicate if a word ends at this node + + +class WordDictionary: + def __init__(self): + # Initialize WordDictionary with a root TrieNode. + self.root = TrieNode() + + def addWord(self, word): + # Add a word to the Trie. + current_node = self.root + + # Traverse each character in the word + for character in word: + # Create a new TrieNode if the character doesn't exist in children + current_node = current_node.children.setdefault(character, TrieNode()) + + # Mark the end of the word at the last character's node + current_node.is_word = True + + def search(self, word): + + def dfs(node, index): + if index == len(word): + # If reached end of the word, check if current node marks the end of a word + return node.is_word + + if word[index] == ".": + # Handle wildcard character '.': Try all possible children + for child in node.children.values(): + if dfs(child, index + 1): + return True + elif word[index] in node.children: + # Regular character: Move to the next node + return dfs(node.children[word[index]], index + 1) + + # If no match found, return False + return False + + # Start DFS from the root of the Trie + return dfs(self.root, 0) diff --git a/number-of-islands/samthekorean.py b/number-of-islands/samthekorean.py new file mode 100644 index 000000000..e00bfb646 --- /dev/null +++ b/number-of-islands/samthekorean.py @@ -0,0 +1,26 @@ +# TC : O(n) where n is the number of elements in the two-dimensional list. +# SC : O(n) where n is the depth of the stack of recursive calls. +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + def dfs(r, c): + # Mark the current cell as visited by setting it to "0" + grid[r][c] = "0" + # Explore all four possible directions (right, down, left, up) + for dr, dc in [(0, 1), (1, 0), (0, -1), (-1, 0)]: + nr, nc = r + dr, c + dc + # Check if the new position is within bounds and is land ("1") + if ( + 0 <= nr < len(grid) + and 0 <= nc < len(grid[0]) + and grid[nr][nc] == "1" + ): + dfs(nr, nc) + + island_count = 0 + # Traverse each cell in the grid + for r in range(len(grid)): + for c in range(len(grid[0])): + if grid[r][c] == "1": # Found an island + island_count += 1 # Increment the island count + dfs(r, c) # Sink the entire island + return island_count # Return the total number of islands diff --git a/pacific-atlantic-water-flow/samthekorean.py b/pacific-atlantic-water-flow/samthekorean.py new file mode 100644 index 000000000..7b3c67bb5 --- /dev/null +++ b/pacific-atlantic-water-flow/samthekorean.py @@ -0,0 +1,44 @@ +# m is number of rows and n is number of columns +# TC : O(m*n) +# SC : O(m*n) +class Solution: + def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]: + ROWS, COLS = len(heights), len(heights[0]) + DIRECTIONS = [(1, 0), (-1, 0), (0, 1), (0, -1)] + pacific, atlantic = set(), set() + result: List[List[int]] = [] + + def dfs( + r: int, c: int, ocean_set: Set[Tuple[int, int]], prev_height: int + ) -> None: + if ( + r < 0 + or r >= ROWS + or c < 0 + or c >= COLS + or (r, c) in ocean_set + or heights[r][c] < prev_height + ): + return + + ocean_set.add((r, c)) + + for dr, dc in DIRECTIONS: + dfs(r + dr, c + dc, ocean_set, heights[r][c]) + + # Water Flow Simulation from Pacific (Top and Left borders) + for col in range(COLS): + dfs(0, col, pacific, heights[0][col]) + dfs(ROWS - 1, col, atlantic, heights[ROWS - 1][col]) + + for row in range(ROWS): + dfs(row, 0, pacific, heights[row][0]) + dfs(row, COLS - 1, atlantic, heights[row][COLS - 1]) + + # Finding cells reachable by both Pacific and Atlantic + for r in range(ROWS): + for c in range(COLS): + if (r, c) in pacific and (r, c) in atlantic: + result.append([r, c]) + + return result