Skip to content

Commit 6db246c

Browse files
committed
solve: binaryTreeMaximumPathSum, graphValidTree, maximumDepthOfBinaryTree, mergeIntervals and reorderList
1 parent 687e199 commit 6db246c

File tree

5 files changed

+131
-0
lines changed

5 files changed

+131
-0
lines changed
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Time Complexity: O(N) - visit each node once.
2+
# Space Complexity: O(H) - recursive call stack, where H is the tree height.
3+
# - O(log N) for balanced trees, O(N) for skewed trees.
4+
5+
class Solution:
6+
def maxPathSum(self, root: Optional[TreeNode]) -> int:
7+
def dfs(node):
8+
nonlocal ans
9+
if not node:
10+
return 0
11+
12+
# get the max path sum from left and right subtrees (ignore negatives)
13+
left = max(dfs(node.left), 0)
14+
right = max(dfs(node.right), 0)
15+
16+
# update the global max path sum including this node
17+
ans = max(ans, left + right + node.val)
18+
19+
# return the max path sum that can be extended to the parent
20+
return max(left, right) + node.val
21+
22+
# initialize with the smallest possible value
23+
ans = float('-inf')
24+
# start DFS from the root
25+
dfs(root)
26+
return ans

graph-valid-tree/yolophg.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Time Complexity: O(N) - iterate through all edges and nodes at most once.
2+
# Space Complexity: O(N) - store the graph as an adjacency list and track visited nodes.
3+
4+
class Solution:
5+
def valid_tree(self, n: int, edges: List[List[int]]) -> bool:
6+
# a tree with 'n' nodes must have exactly 'n-1' edges
7+
if len(edges) != n - 1:
8+
return False
9+
10+
# build an adjacency list (graph representation)
11+
graph = {i: [] for i in range(n)}
12+
for u, v in edges:
13+
graph[u].append(v)
14+
graph[v].append(u)
15+
16+
# use BFS to check if the graph is fully connected and acyclic
17+
visited = set()
18+
queue = [0]
19+
visited.add(0)
20+
21+
while queue:
22+
node = queue.pop(0)
23+
for neighbor in graph[node]:
24+
if neighbor in visited:
25+
continue
26+
visited.add(neighbor)
27+
queue.append(neighbor)
28+
29+
# if we visited all nodes, it's a valid tree
30+
return len(visited) == n
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Time Complexity: O(N) - visit each node once.
2+
# Space Complexity: O(H) - the recursion stack goes as deep as the height of the tree.
3+
# - Worst case (skewed tree): O(N)
4+
# - Best case (balanced tree): O(log N)
5+
6+
class Solution:
7+
def maxDepth(self, root: Optional[TreeNode]) -> int:
8+
# if there's no node, the depth is just 0.
9+
if not root:
10+
return 0
11+
12+
# recursively get the depth of left and right subtrees
13+
# then add 1 for the current node
14+
return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))

merge-intervals/yolophg.py

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Time Complexity: O(N log N) - sorting takes O(N log N), and merging takes O(N)
2+
# Space Complexity: O(N) - store the merged intervals in a new list.
3+
4+
class Solution:
5+
6+
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
7+
# sort the intervals by their start values
8+
intervals.sort(key=lambda x: x[0])
9+
10+
# this will store our final merged intervals
11+
merged = []
12+
# start with the first interval
13+
prev = intervals[0]
14+
15+
# iterate through the sorted intervals
16+
for interval in intervals[1:]:
17+
if interval[0] <= prev[1]:
18+
# overlapping intervals → merge them by updating 'end' value
19+
prev[1] = max(prev[1], interval[1])
20+
else:
21+
# no overlap → add 'prev' to the merged list and update 'prev'
22+
merged.append(prev)
23+
prev = interval
24+
25+
merged.append(prev)
26+
27+
return merged

reorder-list/yolophg.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Time Complexity: O(N) - traverse the list three times:
2+
# (1) find the middle (O(N)),
3+
# (2) reverse the second half (O(N)),
4+
# (3) merge the two halves (O(N)).
5+
# Space Complexity: O(1) - use a few extra pointers, no additional data structures.
6+
7+
class Solution:
8+
def reorderList(self, head: Optional[ListNode]) -> None:
9+
# find the middle of the list using slow & fast pointers
10+
slow, fast = head, head.next
11+
while fast and fast.next:
12+
slow = slow.next
13+
fast = fast.next.next
14+
15+
# reverse the second half of the list
16+
second = slow.next
17+
# cut the list into two halves
18+
slow.next = None
19+
prev = None
20+
21+
while second:
22+
temp = second.next
23+
second.next = prev
24+
prev = second
25+
second = temp
26+
27+
# merge the two halves (alternating nodes)
28+
first, second = head, prev
29+
30+
while second:
31+
temp1, temp2 = first.next, second.next
32+
first.next = second
33+
second.next = temp1
34+
first, second = temp1, temp2

0 commit comments

Comments
 (0)