algorithms

Algorithm implementations
git clone git://git.laack.co/algorithms.git
Log | Files | Refs | README

commit 0bafcf643f45f7f8d8df3c3497831cc515ad0e5d
parent 7f56f71951c5d5e7916c1a3b2c38b423ade21431
Author: Andrew Laack <andrew@laack.co>
Date:   Sun, 13 Sep 2026 11:27:07 -0500

Updated prim visualization, added merkle tree to plan, fixed readme, did subtree encoding lc problem, did dp problem, and graph translation problem

Diffstat:
MREADME | 2+-
Aleetcode/find-duplicate-subtrees/find-duplicate-subtrees.cpp | 46++++++++++++++++++++++++++++++++++++++++++++++
Aleetcode/image-overlap/image-overlap.py | 27+++++++++++++++++++++++++++
Aleetcode/maximum-earnings-from-taxi/maximum-earnings-from-taxi-v1.py | 35+++++++++++++++++++++++++++++++++++
Aleetcode/maximum-earnings-from-taxi/maximum-earnings-from-taxi-v2.py | 40++++++++++++++++++++++++++++++++++++++++
Mplan.txt | 3++-
Mvisualizations/prim.py | 60++++++++++++++++++++++++++----------------------------------
7 files changed, 177 insertions(+), 36 deletions(-)

diff --git a/README b/README @@ -1,3 +1,3 @@ Algorithms -========= +========== This is a repo containing algorithm implementations. diff --git a/leetcode/find-duplicate-subtrees/find-duplicate-subtrees.cpp b/leetcode/find-duplicate-subtrees/find-duplicate-subtrees.cpp @@ -0,0 +1,46 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + + unordered_map<string,int> subtrees {}; + vector<TreeNode*> matching {}; + + string inOrder(TreeNode* root) { + if(root == nullptr) { + return ""; + } + string current = ""; + string left = "L" + inOrder(root->left); + current.append(left); + current.append(to_string(root->val)); + current.append(", "); + string right = "R" + inOrder(root->right); + current.append(right); + + if(subtrees[current] == 0) { + subtrees[current] += 1; + } else { + if (subtrees[current] == 1) { + subtrees[current] = 2; // won't be added to return again for multi-dupes + matching.push_back(root); + } + } + + return current; + } + + vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) { + inOrder(root); + return matching; + } +}; diff --git a/leetcode/image-overlap/image-overlap.py b/leetcode/image-overlap/image-overlap.py @@ -0,0 +1,27 @@ +class Solution: + + def safe_read(self,img1,x,y): + if y >= len(img1) or x >= len(img1[y]) or x < 0 or y < 0: + return 0 + return img1[y][x] + + # we shift img1 + def shift_and_check(self,img1,img2,shift_x,shift_y): + count = 0 + for y in range(len(img2)): + for x in range(len(img2[y])): + if img2[y][x] == 1: + if self.safe_read(img1,x-shift_x, y-shift_y): + count += 1 + return count + + def largestOverlap(self, img1: List[List[int]], img2: List[List[int]]) -> int: + best = 0 + + for y in range(len(img1)): + for mult_y in [-1,1]: + for x in range(len(img1[y])): + for mult_x in [-1,1]: + best = max(self.shift_and_check(img1,img2,x*mult_x,y*mult_y), best) + + return best diff --git a/leetcode/maximum-earnings-from-taxi/maximum-earnings-from-taxi-v1.py b/leetcode/maximum-earnings-from-taxi/maximum-earnings-from-taxi-v1.py @@ -0,0 +1,35 @@ +def start(e): + return e[0] +class Solution: + def best_from(self,current_ride_index,rides): + + if current_ride_index in self.mem: + return self.mem[current_ride_index] + + if current_ride_index >= len(rides): + return 0 + + ride = rides[current_ride_index] + ending = ride[1] + best_without = self.best_from(current_ride_index+1,rides) + + n_idx = current_ride_index+1 + for i in range(current_ride_index+1, len(rides) + 1): + if i >= len(rides): + n_idx = i + break + if rides[i][0] >= ending: + n_idx = i + break + + best_with = self.best_from(n_idx, rides) + + res = max(best_with + (ride[1] - ride[0]) + ride[2], best_without) + self.mem[current_ride_index] = res + return res + + + def maxTaxiEarnings(self, n: int, rides: List[List[int]]) -> int: + rides.sort(key=start) + self.mem = {} + return self.best_from(0,rides) diff --git a/leetcode/maximum-earnings-from-taxi/maximum-earnings-from-taxi-v2.py b/leetcode/maximum-earnings-from-taxi/maximum-earnings-from-taxi-v2.py @@ -0,0 +1,40 @@ +def start(e): + return e[0] +class Solution: + + def binary_search_find(self, rides, left, right, target): + while left < right: + mid = left + (right - left) // 2 + if rides[mid][0] < target: + left = mid + 1 + else: + right = mid + if left < len(rides) and rides[left][0] >= target: + return left + return -1 + + + def best_from(self,current_ride_index,rides): + + if current_ride_index in self.mem: + return self.mem[current_ride_index] + + if current_ride_index >= len(rides) or current_ride_index == -1: + return 0 + + ride = rides[current_ride_index] + ending = ride[1] + best_without = self.best_from(current_ride_index+1,rides) + + n_idx = self.binary_search_find(rides,current_ride_index,len(rides)-1,ride[1]) + best_with = self.best_from(n_idx, rides) + + res = max(best_with + (ride[1] - ride[0]) + ride[2], best_without) + self.mem[current_ride_index] = res + return res + + + def maxTaxiEarnings(self, n: int, rides: List[List[int]]) -> int: + rides.sort(key=start) + self.mem = {} + return self.best_from(0,rides) diff --git a/plan.txt b/plan.txt @@ -10,6 +10,7 @@ these are the things I want to learn, ordered - quickselect x lc 1 - lc 2 - - visualize - perlin noise - visualize + x merkle tree + x find duplicate subtrees (this isn't a merkle tree, but builds on the idea of encoding subtrees in a unique way) diff --git a/visualizations/prim.py b/visualizations/prim.py @@ -9,7 +9,7 @@ pygame.init() display = pygame.display.set_mode((5120,1440)) VERTICES = 100 -EDGES = 200 +EDGES = 1000 white = (255, 255, 255) red = (255, 0, 0) @@ -71,6 +71,12 @@ while True: mst = [] + start = random.choice(list(graph.keys())) + start.visited = True + visited_vertices.add(start) + for edge in graph[start]: + heapq.heappush(edge_heap, edge) + while True: for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -78,46 +84,32 @@ while True: quit() display.fill(black) - for vertex in graph: vertex.draw_vertex(display) - for edge in edge_list: edge.draw_edge(display, light_grey) - for edge in mst: edge.draw_edge(display, white) + item = None + while edge_heap: + candidate = heapq.heappop(edge_heap) + if (candidate.v1 in visited_vertices) != (candidate.v2 in visited_vertices): + item = candidate + break - if len(edge_heap) == 0: - start = random.choice(list(graph.keys())) - visited_vertices.add(start) - edges = graph[start] - for edge in edges: - heapq.heappush(edge_heap, edge) - else: - item = None - while True: - if len(edge_heap) > 0: - item = heapq.heappop(edge_heap) - v1_visited = item.v1 in visited_vertices - v2_visited = item.v2 in visited_vertices - if v1_visited != v2_visited: - break - else: - item = None - break - - if item != None: - new_vertex = item.v2 if item.v1 in visited_vertices else item.v1 - visited_vertices.add(new_vertex) - new_vertex.visited = True - mst.append(item) - edges = graph[new_vertex] - for edge in edges: - heapq.heappush(edge_heap, edge) - else: + if item is None: + pygame.display.update() + if len(visited_vertices) == VERTICES: pygame.image.save(display, "out.jpg") - break - time.sleep(.1) + break + + new_vertex = item.v2 if item.v1 in visited_vertices else item.v1 + visited_vertices.add(new_vertex) + new_vertex.visited = True + mst.append(item) + for edge in graph[new_vertex]: + heapq.heappush(edge_heap, edge) + + time.sleep(.1) pygame.display.update()