Skip to content

Commit

Permalink
Graph Recipes Polish
Browse files Browse the repository at this point in the history
  • Loading branch information
hariharanragothaman committed Jan 19, 2024
1 parent b115757 commit 620dfd3
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 217 deletions.
14 changes: 14 additions & 0 deletions graphs/find_path.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Functions for finding paths in graphs.
"""
from collections import defaultdict

def find_path(graph, start, end, path=[]):
"""
Expand All @@ -22,11 +23,14 @@ def find_all_path(graph, start, end, path=[]):
Find all paths between two nodes using recursion and backtracking
"""
path = path + [start]

if start == end:
return [path]
if not start in graph:
return []

paths = []

for node in graph[start]:
if node not in path:
newpaths = find_all_path(graph, node, end, path)
Expand All @@ -51,3 +55,13 @@ def find_shortest_path(graph, start, end, path=[]):
if not shortest or len(newpath) < len(shortest):
shortest = newpath
return shortest

if __name__ == '__main__':
edges = [[4, 3, 1], [3, 2, 4], [3], [4], []]
graph = defaultdict(list)
for i, e in enumerate(edges):
for d in e:
graph[i].append(d)
print("The graph is:", graph)
paths = find_all_path(start=0, end=4)
print("All paths are", paths)
53 changes: 52 additions & 1 deletion graphs/lca.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,55 @@ def __call__(self, a, b):
b = self.time[b]
if a > b:
a, b = b, a
return self.path[self.rmq.query(a, b)]
return self.path[self.rmq.query(a, b)]

def lca_recursive(self, root, a, b):
# Standard Recipe to find the lowest-common ancestor
if root is None or root is a or root is b:
return root
left = self.lca(root.left, a, b)
right = self.lca(root.right, a, b)
if left is not None and right is not None:
return root
return left if left else right


class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None

class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
stack = [root, ]
parent_map = {root: None}

while stack:
node = stack.pop()
if node.left:
parent_map[node.left] = node
stack.append(node.left)
if node.right:
parent_map[node.right] = node
stack.append(node.right)

if p not in parent_map or q not in parent_map:
return None

ancestors = set()
while p :
ancestors.add(p)
p = parent_map[p]

while q not in ancestors:
q = parent_map[q]
return q


if __name__ == "__main__":
g = {0: [1], 1: [2, 3, 4], 2: [5, 6], 3: [1], 4: [1, 7], 5: [2], 6: [2], 7: [4]}
print("The graph is:", g)
lca = LCA(1, g)
result = lca(5, 6)
print("The lowest common ancestor is:", result)
46 changes: 0 additions & 46 deletions graphs/misc/find_all_paths_from_source_to_target.py

This file was deleted.

14 changes: 0 additions & 14 deletions graphs/misc/lca_recursion.py

This file was deleted.

32 changes: 0 additions & 32 deletions graphs/misc/lca_tree.py

This file was deleted.

71 changes: 0 additions & 71 deletions graphs/misc/lca_with_pre_processing_seg_tree.py

This file was deleted.

50 changes: 0 additions & 50 deletions graphs/misc/tree_diameter_using_dfs.py

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,44 @@
from collections import defaultdict, deque


def find_tree_diameter(g):
def find_tree_diameter(g, n):
"""
Standard awesome problem
So for each node, I want to find the maximum distance to another node
:param g:
:return:
"""
# We can approach this question in the binary tree way (or) the graph way
# Tree - Post order traversal - This in itself is DFS template only
# Graph - Use routine DFS - Remember - tree is an undirected graph

diameter_of_tree = 0

for i in range(1, n + 1):
print(f"Considering {i} as root")
curr_max_length = 0
q = deque()
q.append((i, 0))
visited = set()

while q:
print("The queue is:", q)
node, length = q.pop()
visited.add(node)
curr_max_length = max(length, curr_max_length)

for nei in g[node]:
if nei not in visited:
q.append((nei, length + 1))

print(f"The max_length for {i} is: {curr_max_length}")
diameter_of_tree = max(curr_max_length, diameter_of_tree)
print("*****************************************************")

return diameter_of_tree


def find_tree_diameter_optimized(g):
"""
Standard awesome problem
So for each node, I want to find the maximum distance to another node
Expand Down Expand Up @@ -53,7 +90,6 @@ def find_tree_diameter(g):

return diameter_of_tree


if __name__ == "__main__":
n = int(input())
g = defaultdict(list)
Expand All @@ -62,5 +98,5 @@ def find_tree_diameter(g):
g[u].append(v)
g[v].append(u)
# print(g)
result = find_tree_diameter(g)
result = find_tree_diameter(g, n)
print(result)

0 comments on commit 620dfd3

Please sign in to comment.