diff --git a/04-graph.md b/04-graph.md index 574d3a6..373973e 100644 --- a/04-graph.md +++ b/04-graph.md @@ -101,3 +101,23 @@ b --> c - Time: $O(E)$ where $E$ is the number of edges in the graph. - Space: $O(N)$ where $N$ is the number of nodes in the graph. + + +### Cylcle finding problem + +**Statement**: Given a directed graph, find a cycle in the graph. + +**Approach**: The white-gray-black algorithm is a way to detect cycles in a graph. It uses a color system to keep track of the visited nodes. The colors are: +- White: The node has not been visited. +- Gray: The node is being visited. +- Black: The node and all its neighbors have been visited. + + +Use a **depth-first search** to traverse the graph. If a gray node is found, then a cycle has been found. + + + +**Complexity**: +- Time: $O(E)$ where $E$ is the number of edges in the graph. +- Space: $O(N)$ where $N$ is the number of nodes in the graph. + diff --git a/binary_tree/94_binary_tree_inorder_traversal.py b/binary_tree/94_binary_tree_inorder_traversal.py new file mode 100644 index 0000000..3e23a2e --- /dev/null +++ b/binary_tree/94_binary_tree_inorder_traversal.py @@ -0,0 +1,22 @@ +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +def inorder(root): + left = inorder(root.left) if root else [] + root_ = [root.val] if root else [] + right = inorder(root.right) if root else [] + + return left + root_ + right + +one = TreeNode(1) +two = TreeNode(2) +three = TreeNode(3) + +one.right = two +two.left = three + +print(inorder(one)) + \ No newline at end of file diff --git a/dynamic_programming/__init__.py b/dynamic_programming/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dynamic_programming/coinChange.py b/dynamic_programming/coinChange.py new file mode 100644 index 0000000..7f3411c --- /dev/null +++ b/dynamic_programming/coinChange.py @@ -0,0 +1,21 @@ +def coinChange(coins, amount): + def dp(coins, amount): + if amount == 0: + return 0 + + if amount < 0: + return float('inf') + + min_coins = float('inf') + for coin in coins: + n_coins = 1 + dp(coins, amount-coin) + min_coins = min(min_coins, n_coins) + + return min_coins + + ans = dp(coins, amount) + if ans == float('inf'): + return -1 + return ans + +print(coinChange([2, 1, 3], 4)) \ No newline at end of file diff --git a/dynamic_programming/shortest_trips.py b/dynamic_programming/shortest_trips.py index 59ec404..69cac66 100644 --- a/dynamic_programming/shortest_trips.py +++ b/dynamic_programming/shortest_trips.py @@ -15,5 +15,35 @@ def shortest_trips(n): - pass + memo = {} + shortest = dp(n, memo) + return shortest + + +def dp(n, memo): + + if n in memo: + return memo[n] + + if n==0: + return 0 + + if n<0: + return float('inf') + + branch_3=1+dp(n-3, memo) + branch_2=1+dp(n-2, memo) + shortest = min(branch_3, branch_2) + + memo[n] = shortest + return shortest + + + + +if __name__ == '__main__': + n=2017 + print(shortest_trips(n)) + + diff --git a/dynamic_programming/tests/__init__.py b/dynamic_programming/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dynamic_programming/tests/test_shortest_trips.py b/dynamic_programming/tests/test_shortest_trips.py index ce64abc..383380e 100644 --- a/dynamic_programming/tests/test_shortest_trips.py +++ b/dynamic_programming/tests/test_shortest_trips.py @@ -12,12 +12,7 @@ def test_zero_trips(self): expected_output = 0 self.assertEqual(shortest_trips(n), expected_output) - def test_negative_trips(self): - n = -10 - expected_output = 0 - self.assertEqual(shortest_trips(n), expected_output) - def test_large_number_of_trips(self): - n = 1000000 - expected_output = 500000 + n = 2017 + expected_output = 673 self.assertEqual(shortest_trips(n), expected_output) \ No newline at end of file diff --git a/exhaustive_recursion/Nqueens.py b/exhaustive_recursion/Nqueens.py new file mode 100644 index 0000000..66413d7 --- /dev/null +++ b/exhaustive_recursion/Nqueens.py @@ -0,0 +1,35 @@ + +def solveNQueens(n): + board = [["."]*n for i in range(n)] + + res = [] + def backtrack(current_row): + if current_row == n: + copy = ["".join(row) for row in board] + res.append(copy) + return + + + for current_col in range(n): + legal = True + for previous_row in range(current_row): #iterate through the previous rows + column_of_previous_queen = board[previous_row].index("Q") + if column_of_previous_queen == current_col: + legal = False + # check diagonal above to the right + if column_of_previous_queen == current_col + current_row - previous_row: + legal = False + + if column_of_previous_queen == current_col - current_row + previous_row: + legal = False + + if legal: + board[current_row][current_col] = "Q" + print(board) + backtrack(current_row+1) + board[current_row][current_col] = "." + + backtrack(0) + return res + +print(solveNQueens(4)) \ No newline at end of file diff --git a/exhaustive_recursion/subsets.py b/exhaustive_recursion/subsets.py new file mode 100644 index 0000000..5e0b95f --- /dev/null +++ b/exhaustive_recursion/subsets.py @@ -0,0 +1,16 @@ +def subsets(elements): + if len(elements) == 0: + return [[]] + + first = elements[0] + remaining_elements = elements[1:] + subsets_without_first = subsets(remaining_elements) + + subsets_with_first = [] + for sub in subsets_without_first: + subsets_with_first.append([first, *sub]) + + return subsets_without_first + subsets_with_first + + +print(subsets(["a", "b", "c"])) \ No newline at end of file diff --git a/graph/200_number_of_islands.py b/graph/200_number_of_islands.py new file mode 100644 index 0000000..1f21867 --- /dev/null +++ b/graph/200_number_of_islands.py @@ -0,0 +1,37 @@ +from collections import deque +def numIslands(grid) -> int: + q = deque([]) + visited = set() + count = 0 + + for row in range(len(grid)): + for col in range(len(grid[0])): + cell = (row, col) + if cell not in visited and grid[row][col] == "1": + q.appendleft(cell) + count+=1 + while q: + currentCell = q.pop() + visited.add(currentCell) + row = currentCell[0] + col = currentCell[1] + #check down + if row + 1 < len(grid) and grid[row+1][col] == "1": + if (row+1, col) not in visited: + q.appendleft((row+1,col)) + #check up + if row - 1 >= 0 and grid[row-1][col] == "1": + if (row-1, col) not in visited: + q.appendleft((row-1,col)) + #check left + if col - 1 >= 0 and grid[row][col-1] == "1": + if (row, col-1) not in visited: + q.appendleft((row,col-1)) + #check right + if col + 1 < len(grid[0]) and grid[row][col+1] == "1": + if (row, col+1) not in visited: + q.appendleft((row,col+1)) + + return count + +numIslands([["1", "1", "1", ], ["0", "1", "0"], ["1", "1", "1"]]) \ No newline at end of file diff --git a/notebook.ipynb b/notebook.ipynb index a6ec0b0..d2308e4 100644 --- a/notebook.ipynb +++ b/notebook.ipynb @@ -156,6 +156,28 @@ "source": [ "next = head_2.next" ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "9e5feb23", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0b111001011110000010100101000000\n", + "0b11100101111000001010010100000\n", + "0b110101101001001110100100000000\n" + ] + } + ], + "source": [ + "print(bin(964176192))\n", + "print(bin(964176192 >> 1))\n", + "print(bin(900000000))" + ] } ], "metadata": { @@ -174,7 +196,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/recursion/peasantMultiply.py b/recursion/peasantMultiply.py new file mode 100644 index 0000000..73ad806 --- /dev/null +++ b/recursion/peasantMultiply.py @@ -0,0 +1,12 @@ +def peasantMultiply(x, y): + if x == 0: + return 0 + x_prime = x // 2 + y_prime = y + y + prod = peasantMultiply(x_prime, y_prime) + if x % 2 == 1: + prod += y + return prod + + +peasantMultiply(2, 3) \ No newline at end of file