diff --git a/longest-substring-without-repeating-characters/dusunax.py b/longest-substring-without-repeating-characters/dusunax.py new file mode 100644 index 000000000..d11cbd638 --- /dev/null +++ b/longest-substring-without-repeating-characters/dusunax.py @@ -0,0 +1,63 @@ +''' +# 3. Longest Substring Without Repeating Characters + +use a set to store the characters in the current substring. + + +## Time and Space Complexity + +### Solution 1: using set + +``` +TC: O(n) +SC: O(n) +``` + +#### TC is O(n): +- iterating with end pointer through the string once. = O(n) +- inner while loop runs at most once for each character in the string. = Amortized O(1) + +#### SC is O(n): +- using a set to store the characters in the current substring. = O(n) + +### Solution 2: using ASCII array + +``` +TC: O(n) +SC: O(128) +``` + +#### TC is O(n): +- iterating with end pointer through the string once. = O(n) +- checking if the character is in the current substring. + +#### SC is O(1): +- using an array to store the characters in the current substring. = constant space O(128) +''' +class Solution: + def lengthOfLongestSubstringWithSet(self, s: str) -> int: + max_count = 0 + start = 0 + substrings = set() # SC: O(n) + + for end in range(len(s)): # TC: O(n) + while s[end] in substrings: # TC: Amortized O(1) + substrings.remove(s[start]) + start += 1 + substrings.add(s[end]) + max_count = max(max_count, end - start + 1) + + return max_count + + def lengthOfLongestSubstring(self, s: str) -> int: + max_count = 0 + start = 0 + char_index = [-1] * 128 # SC: O(128) + + for end in range(len(s)): # TC: O(n) + if char_index[ord(s[end])] >= start: + start = char_index[ord(s[end])] + 1 + char_index[ord(s[end])] = end + max_count = max(max_count, end - start + 1) + + return max_count diff --git a/number-of-islands/dusunax.py b/number-of-islands/dusunax.py new file mode 100644 index 000000000..6a8d80ede --- /dev/null +++ b/number-of-islands/dusunax.py @@ -0,0 +1,38 @@ +''' +# 200. Number of Islands + +use DFS to find the number of islands (to find the all the possible cases) + +## Time and Space Complexity + +``` +TC: O(m * n) +SC: O(m * n) +``` + +### TC is O(m * n): +- dfs function is called for each cell in the grid for checking is the land ("1") = O(m * n) + +### SC is O(m * n): +- using a recursive function, the call stack can go as deep as the number of cells in the grid in the worst case. = O(m * n) +''' +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + def dfs(x, y): + if x < 0 or y < 0 or y >= len(grid) or x >= len(grid[0]) or grid[y][x] == "0" : + return + + grid[y][x] = "0" + dfs(x, y + 1) + dfs(x - 1, y) + dfs(x, y - 1) + dfs(x + 1, y) + + island_count = 0 + for y in range(len(grid)): + for x in range(len(grid[0])): + if grid[y][x] == "1": + dfs(x, y) + island_count += 1 + + return island_count diff --git a/reverse-linked-list/dusunax.py b/reverse-linked-list/dusunax.py new file mode 100644 index 000000000..569cde36c --- /dev/null +++ b/reverse-linked-list/dusunax.py @@ -0,0 +1,24 @@ +''' +# 206. Reverse Linked List + +iterate through the linked list and reverse the direction of the pointers. + +## Time and Space Complexity + +``` +TC: O(n) +SC: O(1) +``` +''' +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + prev = None + current = head + + while current is not None: # TC: O(n) + next_list_temp = current.next + current.next = prev + prev = current + current = next_list_temp + + return prev diff --git a/set-matrix-zeroes/dusunax.py b/set-matrix-zeroes/dusunax.py new file mode 100644 index 000000000..b43766109 --- /dev/null +++ b/set-matrix-zeroes/dusunax.py @@ -0,0 +1,67 @@ +''' +# 73. Set Matrix Zeroes +# solution reference: https://www.algodale.com/problems/set-matrix-zeroes/ +''' +class Solution: + ''' + ### TC is O(m * n): + - iterating through every cells, to find the zero cells. = O(m * n) 1️⃣ + - iterating through every cells, to update the rows. = O(m * n) 2️⃣ + - iterating through every cells, to update the columns. = O(m * n) 3️⃣ + + ### SC is O(m + n): + - using each set to store the rows(O(m)) and columns(O(n)) that have zero. = O(m + n) + ''' + def setZeroesWithSet(self, matrix: List[List[int]]) -> None: + zero_rows = set() # SC: O(m) + zero_cols = set() # SC: O(n) + + for r in range(len(matrix)): # TC: O(m * n) + for c in range(len(matrix[0])): + if matrix[r][c] == 0: + zero_rows.add(r) + zero_cols.add(c) + + for r in zero_rows: # TC: O(m * n) + for i in range(len(matrix[0])): + matrix[r][i] = 0 + + for c in zero_cols: # TC: O(m * n) + for i in range(len(matrix)): + matrix[i][c] = 0 + + ''' + ### TC is O(m * n): + - check if the first row or column has zero. = O(m + n) + - iterating through every cells, if it has zero, mark the first row and column. = O(m * n) 1️⃣ + - update the matrix based on the marks(0) in the first row and column. = O(m * n) 2️⃣ + - if the first row or column has zero, iterating through every cells, in the first row or column and updating it. = O(m + n) + + ### SC is O(1): + - using the first_row_has_zero and first_col_has_zero to store the zero information. = O(1) + ''' + def setZeroesWithMarkerAndVariable(self, matrix: List[List[int]]) -> None: + rows = len(matrix) + cols = len(matrix[0]) + + first_row_has_zero = any(matrix[0][j] == 0 for j in range(cols)) # TC: O(n), SC: O(1) + first_col_has_zero = any(matrix[i][0] == 0 for i in range(rows)) # TC: O(m), SC: O(1) + + for r in range(1, rows): # TC: O(m * n) + for c in range(1, cols): + if matrix[r][c] == 0: + matrix[r][0] = 0 + matrix[0][c] = 0 + + for r in range(1, rows): # TC: O(m * n) + for c in range(1, cols): + if matrix[r][0] == 0 or matrix[0][c] == 0: + matrix[r][c] = 0 + + if first_row_has_zero: + for c in range(cols): # TC: O(n) + matrix[0][c] = 0 + + if first_col_has_zero: + for r in range(rows): # TC: O(m) + matrix[r][0] = 0 diff --git a/unique-paths/dusunax.py b/unique-paths/dusunax.py new file mode 100644 index 000000000..dac03df5f --- /dev/null +++ b/unique-paths/dusunax.py @@ -0,0 +1,21 @@ +''' +# 62. Unique Paths + +use dynamic programming & a dp table to store the number of ways to reach each cell. + +### TC is O(m * n): +- iterating through every cell in the grid. = O(m * n) +- updating each cell in the grid. = O(1) + +### SC is O(m * n): +- using a dp table (2D array) to store the number of ways to reach each cell. = O(m * n) +''' +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + dp = [[1] * n for _ in range(m)] + + for y in range(1, m): + for x in range(1, n): + dp[y][x] = dp[y - 1][x] + dp[y][x - 1] + + return dp[m - 1][n - 1]