diff --git a/binary-tree-maximum-path-sum/dolphinflow86.py b/binary-tree-maximum-path-sum/dolphinflow86.py new file mode 100644 index 0000000000..895f5cf5f0 --- /dev/null +++ b/binary-tree-maximum-path-sum/dolphinflow86.py @@ -0,0 +1,32 @@ +# N is the number of nodes, and H is the height of the binary tree. +# TC: O(N) - visits each node once in post-order DFS +# SC: O(H) - recursion call stack proportional to tree height (O(N) in worst case) + +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + + +class Solution: + + def maxPathSum(self, root) -> int: + max_sum = float("-inf") + + def max_gain(node) -> int: + nonlocal max_sum + if not node: + return 0 + + left_gain = max(0, max_gain(node.left)) + right_gain = max(0, max_gain(node.right)) + + current_path = node.val + left_gain + right_gain + max_sum = max(max_sum, current_path) + + return node.val + max(left_gain, right_gain) + + max_gain(root) + return max_sum diff --git a/graph-valid-tree/dolphinflow86.py b/graph-valid-tree/dolphinflow86.py new file mode 100644 index 0000000000..4416d5906d --- /dev/null +++ b/graph-valid-tree/dolphinflow86.py @@ -0,0 +1,27 @@ +# V is the number of nodes (n), and E is the number of edges. +# TC: O(V + E) - builds adjacency list and traverses graph with DFS +# SC: O(V + E) - stores graph adjacency list and stack/visited set + + +class Solution: + + def validTree(self, n: int, edges: list[list[int]]) -> bool: + if len(edges) != n - 1: + return False + + adj = [[] for _ in range(n)] + for u, v in edges: + adj[u].append(v) + adj[v].append(u) + + visited = set([0]) + stack = [0] + + while stack: + node = stack.pop() + for neighbor in adj[node]: + if neighbor not in visited: + visited.add(neighbor) + stack.append(neighbor) + + return len(visited) == n diff --git a/merge-intervals/dolphinflow86.py b/merge-intervals/dolphinflow86.py new file mode 100644 index 0000000000..a3ddc563d0 --- /dev/null +++ b/merge-intervals/dolphinflow86.py @@ -0,0 +1,18 @@ +# N is the number of intervals. +# TC: O(N log N) - sorts intervals by start time and merges in a single pass +# SC: O(N) - space for the output array and sorting + + +class Solution: + + def merge(self, intervals: list[list[int]]) -> list[list[int]]: + intervals.sort() + merged = [intervals[0]] + + for interval in intervals[1:]: + if interval[0] <= merged[-1][1]: + merged[-1][1] = max(merged[-1][1], interval[1]) + else: + merged.append(interval) + + return merged diff --git a/missing-number/dolphinflow86.py b/missing-number/dolphinflow86.py new file mode 100644 index 0000000000..53d6c709d8 --- /dev/null +++ b/missing-number/dolphinflow86.py @@ -0,0 +1,15 @@ +# N is the length of array nums. +# TC: O(N) - stores elements in a hash set and performs O(1) lookups +# SC: O(N) - uses a hash set of size N + + +class Solution: + + def missingNumber(self, nums: list[int]) -> int: + num_set = set(nums) + + for i in range(len(nums) + 1): + if i not in num_set: + return i + + return -1 diff --git a/reorder-list/dolphinflow86.py b/reorder-list/dolphinflow86.py new file mode 100644 index 0000000000..b81a642591 --- /dev/null +++ b/reorder-list/dolphinflow86.py @@ -0,0 +1,45 @@ +# N is the number of nodes in the linked list. +# TC: O(N) - finds middle, reverses second half, and merges in linear time +# SC: O(1) - modifies links in place using constant extra pointers + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next + + +class Solution: + + def reorderList(self, head) -> None: + """ + Do not return anything, modify head in-place instead. + """ + if not head or not head.next or not head.next.next: + return + + # 1. Find the middle of the linked list + slow, fast = head, head + while fast.next and fast.next.next: + slow = slow.next + fast = fast.next.next + + # 2. Reverse the second half of the list + prev = None + curr = slow.next + slow.next = None + + while curr: + next_node = curr.next + curr.next = prev + prev = curr + curr = next_node + + # 3. Merge two halves (head and prev) + first, second = head, prev + while second: + tmp1, tmp2 = first.next, second.next + first.next = second + second.next = tmp1 + first = tmp1 + second = tmp2