Skip to content

Commit

Permalink
Add cycle finding algorithm and shortest trips implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
romarowski committed Mar 30, 2024
1 parent bbc96f2 commit 2b2ae78
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 9 deletions.
20 changes: 20 additions & 0 deletions 04-graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

22 changes: 22 additions & 0 deletions binary_tree/94_binary_tree_inorder_traversal.py
Original file line number Diff line number Diff line change
@@ -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))

Empty file added dynamic_programming/__init__.py
Empty file.
21 changes: 21 additions & 0 deletions dynamic_programming/coinChange.py
Original file line number Diff line number Diff line change
@@ -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))
32 changes: 31 additions & 1 deletion dynamic_programming/shortest_trips.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))



Empty file.
9 changes: 2 additions & 7 deletions dynamic_programming/tests/test_shortest_trips.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
35 changes: 35 additions & 0 deletions exhaustive_recursion/Nqueens.py
Original file line number Diff line number Diff line change
@@ -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))
16 changes: 16 additions & 0 deletions exhaustive_recursion/subsets.py
Original file line number Diff line number Diff line change
@@ -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"]))
37 changes: 37 additions & 0 deletions graph/200_number_of_islands.py
Original file line number Diff line number Diff line change
@@ -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"]])
24 changes: 23 additions & 1 deletion notebook.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand All @@ -174,7 +196,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
"version": "3.10.12"
}
},
"nbformat": 4,
Expand Down
12 changes: 12 additions & 0 deletions recursion/peasantMultiply.py
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 2b2ae78

Please sign in to comment.