From 4e2b2a7eee4a626be2f419949196fa2c732f582a Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 17:33:41 -0500 Subject: [PATCH 01/12] add: GraphDeepCopy --- java/Graphs/GraphDeepCopy.java | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 java/Graphs/GraphDeepCopy.java diff --git a/java/Graphs/GraphDeepCopy.java b/java/Graphs/GraphDeepCopy.java new file mode 100644 index 0000000..58013ad --- /dev/null +++ b/java/Graphs/GraphDeepCopy.java @@ -0,0 +1,46 @@ +import java.util.HashMap; +import java.util.Map; + +import DS.GraphNode; + +/* + // Definition of GraphNode: + class GraphNode { + public int val; + public List neighbors; + public MultiLevelListNode(int val) { + this.val = val; + this.neighbors = new ArrayList<>(); + } + } + */ + +public class GraphDeepCopy { + public GraphNode graphDeepCopy(GraphNode node) { + if (node == null) { + return null; + } + Map cloneMap = new HashMap<>(); + return dfs(node, cloneMap); + } + + private GraphNode dfs(GraphNode node, Map cloneMap) { + // If this node was already cloned, then return this previously + // cloned node. + if (cloneMap.containsKey(node)) { + return cloneMap.get(node); + } + // Clone the current node. + GraphNode clonedNode = new GraphNode(node.val); + // Store the current clone to ensure it doesn't need to be created + // again in future DFS calls. + cloneMap.put(node, clonedNode); + // Iterate through the neighbors of the current node to connect + // their clones to the current cloned node. + for (GraphNode neighbor : node.neighbors) { + GraphNode clonedNeighbor = dfs(neighbor, cloneMap); + clonedNode.neighbors.add(clonedNeighbor); + } + return clonedNode; + } +} From f08e78f98f43efc2e614780c7e01ca42f9b71e2c Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 17:43:10 -0500 Subject: [PATCH 02/12] add: CountIslands --- java/Graphs/CountIslands.java | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 java/Graphs/CountIslands.java diff --git a/java/Graphs/CountIslands.java b/java/Graphs/CountIslands.java new file mode 100644 index 0000000..87fc024 --- /dev/null +++ b/java/Graphs/CountIslands.java @@ -0,0 +1,39 @@ +public class CountIslands { + public int countIslands(int[][] matrix) { + if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) { + return 0; + } + int count = 0; + for (int r = 0; r < matrix.length; r++) { + for (int c = 0; c < matrix[0].length; c++) { + // If a land cell is found, perform DFS to explore the full + // island, and include this island in our count. + if (matrix[r][c] == 1) { + dfs(r, c, matrix); + count++; + } + } + } + return count; + } + + private void dfs(int r, int c, int[][] matrix) { + // Mark the current land cell as visited. + matrix[r][c] = -1; + // Define direction vectors for up, down, left, and right. + int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; + // Recursively call DFS on each neighboring land cell to continue + // exploring this island. + for (int[] d : dirs) { + int nextR = r + d[0]; + int nextC = c + d[1]; + if (isWithinBounds(nextR, nextC, matrix) && matrix[nextR][nextC] == 1) { + dfs(nextR, nextC, matrix); + } + } + } + + private boolean isWithinBounds(int r, int c, int[][] matrix) { + return 0 <= r && r < matrix.length && 0 <= c && c < matrix[0].length; + } +} From 8f239f6ee7663f39c0adcb46c016228a5ede1eb7 Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 17:57:18 -0500 Subject: [PATCH 03/12] add: MatrixInfection --- java/Graphs/MatrixInfection.java | 53 ++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 java/Graphs/MatrixInfection.java diff --git a/java/Graphs/MatrixInfection.java b/java/Graphs/MatrixInfection.java new file mode 100644 index 0000000..da59afc --- /dev/null +++ b/java/Graphs/MatrixInfection.java @@ -0,0 +1,53 @@ +import java.util.ArrayDeque; +import java.util.Deque; + +public class MatrixInfection { + public int matrixInfection(int[][] matrix) { + int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; + Deque queue = new ArrayDeque<>(); + int ones, seconds; + ones = seconds = 0; + // Count the total number of uninfected cells and add each infected + // cell to the queue to represent level 0 of the level-order + // traversal. + for (int r = 0; r < matrix.length; r++) { + for (int c = 0; c < matrix[0].length; c++) { + if (matrix[r][c] == 1) { + ones += 1; + } else if (matrix[r][c] == 2) { + queue.offer(new int[]{r, c}); + } + } + } + // Use level-order traversal to determine how long it takes to + // infect the uninfected cells. + while (!queue.isEmpty() && ones > 0) { + // 1 second passes with each level of the matrix that's explored. + seconds++; + int size = queue.size(); + for (int i = 0; i < size; i++) { + int[] pos = queue.poll(); + int r = pos[0]; + int c = pos[1]; + // Infect any neighboring 1s and add them to the queue to be + // processed in the next level. + for (int[] d : dirs) { + int nextR = r + d[0]; + int nextC = c + d[1]; + if (isWithinBounds(nextR, nextC, matrix) && matrix[nextR][nextC] == 1) { + matrix[nextR][nextC] = 2; + ones--; + queue.offer(new int[]{nextR, nextC}); + } + } + } + } + // If there are still uninfected cells left, return -1. Otherwise, + // return the time passed. + return ones == 0 ? seconds : -1; + } + + private boolean isWithinBounds(int r, int c, int[][] matrix) { + return 0 <= r && r < matrix.length && 0 <= c && c < matrix[0].length; + } +} From 30ae660aafc703aad0b7e679b7144bd0fd6f147b Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 18:03:31 -0500 Subject: [PATCH 04/12] add: BipartiteGraphValidation --- java/Graphs/BipartiteGraphValidation.java | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 java/Graphs/BipartiteGraphValidation.java diff --git a/java/Graphs/BipartiteGraphValidation.java b/java/Graphs/BipartiteGraphValidation.java new file mode 100644 index 0000000..1a683ea --- /dev/null +++ b/java/Graphs/BipartiteGraphValidation.java @@ -0,0 +1,29 @@ +public class BipartiteGraphValidation { + public boolean bipartiteGraphValidation(int[][] graph) { + int[] colors = new int[graph.length]; + // Determine if each graph component is bipartite. + for (int i = 0; i < graph.length; i++) { + if (colors[i] == 0 && !dfs(i, 1, graph, colors)) { + return false; + } + } + return true; + } + + private boolean dfs(int node, int color, int[][] graph, int[] colors) { + colors[node] = color; + for (int neighbor : graph[node]) { + // If the current neighbor has the same color as the current + // node, the graph is not bipartite. + if (colors[neighbor] == color) { + return false; + } + // If the current neighbor is not colored, color it with the + // other color and continue the DFS. + if (colors[neighbor] == 0 && !dfs(neighbor, -color, graph, colors)) { + return false; + } + } + return true; + } +} From d56c50d40c6d52dbfa8f2b563fc197c9ef1af9f4 Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 18:10:25 -0500 Subject: [PATCH 05/12] add: longestIncreasingPath --- java/Graphs/LongestIncreasingPath.java | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 java/Graphs/LongestIncreasingPath.java diff --git a/java/Graphs/LongestIncreasingPath.java b/java/Graphs/LongestIncreasingPath.java new file mode 100644 index 0000000..07c7147 --- /dev/null +++ b/java/Graphs/LongestIncreasingPath.java @@ -0,0 +1,43 @@ +public class LongestIncreasingPath { + public int longestIncreasingPath(int[][] matrix) { + if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) { + return 0; + } + int res = 0; + int m = matrix.length; + int n = matrix[0].length; + int[][] memo = new int[m][n]; + // Find the longest increasing path starting at each cell. The + // maximum of these is equal to the overall longest increasing + // path. + for (int r = 0; r < m; r++) { + for (int c = 0; c < n; c++) { + res = Math.max(res, dfs(r, c, matrix, memo)); + } + } + return res; + } + + private int dfs(int r, int c, int[][] matrix, int[][] memo) { + if (memo[r][c] != 0) { + return memo[r][c]; + } + int maxPath = 1; + int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; + // The longest path starting at the current cell is equal to the + // longest path of its larger neighboring cells, plus 1. + for (int[] d : dirs) { + int nextR = r + d[0]; + int nextC = c + d[1]; + if (isWithinBounds(nextR, nextC, matrix) && matrix[nextR][nextC] > matrix[r][c]) { + maxPath = Math.max(maxPath, 1 + dfs(nextR, nextC, matrix, memo)); + } + } + memo[r][c] = maxPath; + return maxPath; + } + + private boolean isWithinBounds(int r, int c, int[][] matrix) { + return 0 <= r && r < matrix.length && 0 <= c && c < matrix[0].length; + } +} From 38b7186a33f4bc76c5b6312fb882799cde15cf20 Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 18:48:46 -0500 Subject: [PATCH 06/12] add: shortestTransformationSequence --- .../ShortestTransformationSequence.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 java/Graphs/ShortestTransformationSequence.java diff --git a/java/Graphs/ShortestTransformationSequence.java b/java/Graphs/ShortestTransformationSequence.java new file mode 100644 index 0000000..39f55c3 --- /dev/null +++ b/java/Graphs/ShortestTransformationSequence.java @@ -0,0 +1,57 @@ +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class ShortestTransformationSequence { + public int shortestTransformationSequence(String start, String end, List dictionary) { + Set dictionarySet = new HashSet<>(dictionary); + if (!dictionarySet.contains(start) && !dictionarySet.contains(end)) { + return 0; + } + if (start == end) { + return 1; + } + String lowerCaseAlphabet = "abcdefghijklmnopqrstuvwxyz"; + Deque queue = new ArrayDeque<>(); + Set visited = new HashSet<>(); + queue.offer(start); + visited.add(start); + int dist = 0; + // Use level-order traversal to find the shortest path from the + // start word to the end word. + while (!queue.isEmpty()) { + int size = queue.size(); + for (int j = 0; j < size; j++) { + String currWord = queue.poll(); + // If we found the end word, we've reached it via the + // shortest path. + if (currWord.equals(end)) { + return dist + 1; + } + // Generate all possible words that have a one-letter + // difference to the current word. + char[] currWordArray = currWord.toCharArray(); + for (int i = 0; i < currWord.length(); i++) { + char tmp = currWordArray[i]; + for (char c : lowerCaseAlphabet.toCharArray()) { + currWordArray[i] = c; + String nextWord = new String(currWordArray); + // If 'next_word' exists in the dictionary, it's a + // neighbor of the current word. If unvisited, add it + // to the queue to be processed in the next level. + if (dictionarySet.contains(nextWord) && !visited.contains(nextWord)) { + visited.add(nextWord); + queue.offer(nextWord); + } + } + currWordArray[i] = tmp; + } + } + dist++; + } + // If there is no way to reach the end node, then no path exists. + return 0; + } +} From c8dec58a4b96246ee9df89c200ad03ad07fd1b76 Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 19:06:29 -0500 Subject: [PATCH 07/12] add: ShortestTransformationSequenceOptimized --- .../ShortestTransformationSequence.java | 2 +- ...ortestTransformationSequenceOptimized.java | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 java/Graphs/ShortestTransformationSequenceOptimized.java diff --git a/java/Graphs/ShortestTransformationSequence.java b/java/Graphs/ShortestTransformationSequence.java index 39f55c3..efdd455 100644 --- a/java/Graphs/ShortestTransformationSequence.java +++ b/java/Graphs/ShortestTransformationSequence.java @@ -38,7 +38,7 @@ public int shortestTransformationSequence(String start, String end, List for (char c : lowerCaseAlphabet.toCharArray()) { currWordArray[i] = c; String nextWord = new String(currWordArray); - // If 'next_word' exists in the dictionary, it's a + // If 'nextWord' exists in the dictionary, it's a // neighbor of the current word. If unvisited, add it // to the queue to be processed in the next level. if (dictionarySet.contains(nextWord) && !visited.contains(nextWord)) { diff --git a/java/Graphs/ShortestTransformationSequenceOptimized.java b/java/Graphs/ShortestTransformationSequenceOptimized.java new file mode 100644 index 0000000..52929da --- /dev/null +++ b/java/Graphs/ShortestTransformationSequenceOptimized.java @@ -0,0 +1,77 @@ +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class ShortestTransformationSequenceOptimized { + public int shortestTransformationSequenceOptimized(String start, String end, List dictionary) { + Set dictionarySet = new HashSet<>(dictionary); + if (!dictionarySet.contains(start) && !dictionarySet.contains(end)) { + return 0; + } + if (start == end) { + return 1; + } + Deque startQueue = new ArrayDeque<>(); + Set startVisited = new HashSet<>(); + Deque endQueue = new ArrayDeque<>(); + Set endVisited = new HashSet<>(); + startQueue.offer(start); + startVisited.add(start); + endQueue.offer(end); + endVisited.add(end); + int levelStart, levelEnd; + levelStart = levelEnd = 0; + // Perform a level-order traversal from the start word and another + // from the end word. + while (!startQueue.isEmpty() && !endQueue.isEmpty()) { + // Explore the next level of the traversal that starts from the + // start word. If it meets the other traversal, the shortest + // path between 'start' and 'end' has been found. + levelStart++; + if (exploreLevel(startQueue, startVisited, endVisited, dictionarySet)) { + return levelStart + levelEnd + 1; + } + // Explore the next level of the traversal that starts from the + // end word. + levelEnd++; + if (exploreLevel(endQueue, endVisited, startVisited, dictionarySet)) { + return levelStart + levelEnd + 1; + } + } + // If the traversals never met, then no path exists. + return 0; + } + + // This function explores the next level in the level-order traversal + // and checks if two searches meet. + private boolean exploreLevel(Deque queue, Set visited, Set otherVisited, Set dictionarySet) { + String lowerCaseAlphabet = "abcdefghijklmnopqrstuvwxyz"; + int size = queue.size(); + for (int j = 0; j < size; j++) { + String currWord = queue.poll(); + char[] currWordArray = currWord.toCharArray(); + for (int i = 0; i < currWord.length(); i++) { + char tmp = currWordArray[i]; + for (char c : lowerCaseAlphabet.toCharArray()) { + currWordArray[i] = c; + String nextWord = new String(currWordArray); + // If 'nextWord' has been visited during the other + // traversal, it means both searches have met. + if (otherVisited.contains(nextWord)) { + return true; + } + if (dictionarySet.contains(nextWord) && !visited.contains(nextWord)) { + visited.add(nextWord); + queue.offer(nextWord); + } + } + currWordArray[i] = tmp; + } + } + // If no word has been visited by the other traversal, the searches + // have not met yet. + return false; + } +} From ad8f8992d26ac51f692e4f79c543b934f8513dd6 Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 21:57:31 -0500 Subject: [PATCH 08/12] add: MergingCommunities --- java/Graphs/MergingCommunities.java | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 java/Graphs/MergingCommunities.java diff --git a/java/Graphs/MergingCommunities.java b/java/Graphs/MergingCommunities.java new file mode 100644 index 0000000..0763dc9 --- /dev/null +++ b/java/Graphs/MergingCommunities.java @@ -0,0 +1,60 @@ +import java.util.Arrays; + +public class UnionFind { + int[] parent; + int[] size; + + public UnionFind(int size) { + this.parent = new int[size]; + this.size = new int[size]; + for (int i = 0; i < size; i++) { + this.parent[i] = i; + } + Arrays.fill(this.size, 1); + } + + public void union(int x, int y) { + int repX = find(x); + int repY = find(y); + // If 'repX' represents a larger community, connect + // 'repY 's community to it. + if (this.size[repX] > this.size[repY]) { + this.parent[repY] = repX; + this.size[repX] += this.size[repY]; + } + // Otherwise, connect 'rep_x's community to 'rep_y'. + else { + this.parent[repX] = repY; + this.size[repY] += this.size[repX]; + } + } + + public int find(int x) { + if (x == this.parent[x]) { + return x; + } + // Path compression. + this.parent[x] = find(this.parent[x]); + return this.parent[x]; + } + + public int getSize(int x) { + return this.size[find(x)]; + } +} + +public class MergingCommunities { + UnionFind uf; + + public MergingCommunities(int n) { + this.uf = new UnionFind(n); + } + + public void connect(int x, int y) { + this.uf.union(x, y); + } + + public int getCommunitySize(int x) { + return this.uf.getSize(x); + } +} From c8d8179f91d1ce700627646495713efe39ecf623 Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 22:12:09 -0500 Subject: [PATCH 09/12] add: Prerequisites --- java/Graphs/Prerequisites.java | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 java/Graphs/Prerequisites.java diff --git a/java/Graphs/Prerequisites.java b/java/Graphs/Prerequisites.java new file mode 100644 index 0000000..537c953 --- /dev/null +++ b/java/Graphs/Prerequisites.java @@ -0,0 +1,47 @@ +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Queue; + +public class Prerequisites { + public boolean prerequisites(int n, int[][] prerequisites) { + Map> graph = new HashMap<>(); + int[] inDegrees = new int[n]; + // Represent the graph as an adjacency list and record the in- + // degree of each course. + for (int[] edge : prerequisites) { + int prerequisite = edge[0]; + int course = edge[1]; + graph.putIfAbsent(prerequisite, new ArrayList<>()); + graph.get(prerequisite).add(course); + inDegrees[course]++; + } + Queue queue = new ArrayDeque<>(); + // Add all courses with an in-degree of 0 to the queue. + for (int i = 0; i < n; i++) { + if (inDegrees[i] == 0) { + queue.offer(i); + } + } + int enrolledCourses = 0; + // Perform topological sort. + while (!queue.isEmpty()) { + int node = queue.poll(); + enrolledCourses++; + if (graph.containsKey(node)) { + for (int neighbor : graph.get(node)) { + inDegrees[neighbor]--; + // If the in-degree of a neighboring course becomes 0, add + // it to the queue. + if (inDegrees[neighbor] == 0) { + queue.offer(neighbor); + } + } + } + } + // Return true if we've successfully enrolled in all courses. + return enrolledCourses == n; + } +} From e4c5366a0d918dc88f2cf6fbcb6401d0658de65b Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 22:44:06 -0500 Subject: [PATCH 10/12] add: shortestPath --- java/Graphs/ShortestPath.java | 59 +++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 java/Graphs/ShortestPath.java diff --git a/java/Graphs/ShortestPath.java b/java/Graphs/ShortestPath.java new file mode 100644 index 0000000..12806ec --- /dev/null +++ b/java/Graphs/ShortestPath.java @@ -0,0 +1,59 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; + +public class ShortestPath { + public int[] shortestPath(int n, int[][] edges, int start) { + Map> graph = new HashMap<>(); + int[] distances = new int[n]; + Arrays.fill(distances, Integer.MAX_VALUE); + distances[start] = 0; + // Represent the graph as an adjacency list. + for (int[] edge : edges) { + int u = edge[0]; + int v = edge[1]; + int w = edge[2]; + + graph.putIfAbsent(u, new ArrayList<>()); + graph.putIfAbsent(v, new ArrayList<>()); + graph.get(u).add(new int[]{v, w}); + graph.get(v).add(new int[]{u, w}); + } + PriorityQueue minHeap = new PriorityQueue<>((a, b) -> Integer.compare(a[0], b[0])); + minHeap.offer(new int[]{0, start}); // (distance, node) + // Use Dijkstra's algorithm to find the shortest path between the start node + // and all other nodes. + while (!minHeap.isEmpty()) { + int[] curr = minHeap.poll(); + int currDist = curr[0]; + int currNode = curr[1]; + // If the current distance to this node is greater than the recorded + // distance, we've already found the shortest distance to this node. + if (currDist > distances[currNode]) { + continue; + } + // Update the distances of the neighboring nodes. + for (int[] edge : graph.get(currNode)) { + int neighbor = edge[0]; + int weight = edge[1]; + int neighborDist = currDist + weight; + // Only update the distance if we find a shorter path to this + // neighbor. + if (neighborDist < distances[neighbor]) { + distances[neighbor] = neighborDist; + minHeap.offer(new int[]{neighborDist, neighbor}); + } + } + } + // Convert all infinity values to -1, representing unreachable nodes. + for (int i = 0; i < n; i++) { + if (distances[i] == Integer.MAX_VALUE) { + distances[i] = -1; + } + } + return distances; + } +} From 2351872aad3e42c179d6328be7b7eb214eae3192 Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Tue, 4 Feb 2025 22:58:44 -0500 Subject: [PATCH 11/12] add: ConnectTheDots, fix minor error in MergingCommunities --- java/Graphs/ConnectTheDots.java | 82 +++++++++++++++++++++++++++++ java/Graphs/MergingCommunities.java | 24 +++++---- 2 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 java/Graphs/ConnectTheDots.java diff --git a/java/Graphs/ConnectTheDots.java b/java/Graphs/ConnectTheDots.java new file mode 100644 index 0000000..b543b79 --- /dev/null +++ b/java/Graphs/ConnectTheDots.java @@ -0,0 +1,82 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +class UnionFind { + int[] parent; + int[] size; + + public UnionFind(int size) { + this.parent = new int[size]; + this.size = new int[size]; + for (int i = 0; i < size; i++) { + this.parent[i] = i; + } + Arrays.fill(this.size, 1); + } + + public boolean union(int x, int y) { + int repX = find(x); + int repY = find(y); + if (repX != repY) { + if (this.size[repX] > this.size[repY]) { + this.parent[repY] = repX; + this.size[repX] += this.size[repY]; + } + else { + this.parent[repX] = repY; + this.size[repY] += this.size[repX]; + } + // Return True if both groups were merged. + return true; + } + // Return False if the points belong to the same group. + return false; + } + + public int find(int x) { + if (x == this.parent[x]) { + return x; + } + this.parent[x] = find(this.parent[x]); + return this.parent[x]; + } +} + +public class ConnectTheDots { + public int connectTheDots(int[][] points) { + int n = points.length; + // Create and populate a list of all possible edges. + List edges = new ArrayList<>(); + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + // Manhattan distance. + int cost = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]); + edges.add(new int[]{cost, i, j}); + } + } + // Sort the edges by their cost in ascending order. + Collections.sort(edges, (a, b) -> Integer.compare(a[0], b[0])); + UnionFind uf = new UnionFind(n); + int totalCost, edgesAdded; + totalCost = edgesAdded = 0; + // Use Kruskal's algorithm to create the MST and identify its minimum cost. + for (int[] edge : edges) { + int cost = edge[0]; + int p1 = edge[1]; + int p2 = edge[2]; + // If the points are not already connected (i.e. their representatives are + // not the same), connect them, and add the cost to the total cost. + if (uf.union(p1, p2)) { + totalCost += cost; + edgesAdded++; + // If n - 1 edges have been added to the MST, the MST is complete. + if (edgesAdded == n - 1) { + return totalCost; + } + } + } + return 0; + } +} diff --git a/java/Graphs/MergingCommunities.java b/java/Graphs/MergingCommunities.java index 0763dc9..5e330aa 100644 --- a/java/Graphs/MergingCommunities.java +++ b/java/Graphs/MergingCommunities.java @@ -1,6 +1,6 @@ import java.util.Arrays; -public class UnionFind { +class UnionFind { int[] parent; int[] size; @@ -16,16 +16,18 @@ public UnionFind(int size) { public void union(int x, int y) { int repX = find(x); int repY = find(y); - // If 'repX' represents a larger community, connect - // 'repY 's community to it. - if (this.size[repX] > this.size[repY]) { - this.parent[repY] = repX; - this.size[repX] += this.size[repY]; - } - // Otherwise, connect 'rep_x's community to 'rep_y'. - else { - this.parent[repX] = repY; - this.size[repY] += this.size[repX]; + if (repX != repY) { + // If 'repX' represents a larger community, connect + // 'repY 's community to it. + if (this.size[repX] > this.size[repY]) { + this.parent[repY] = repX; + this.size[repX] += this.size[repY]; + } + // Otherwise, connect 'rep_x's community to 'rep_y'. + else { + this.parent[repX] = repY; + this.size[repY] += this.size[repX]; + } } } From d91c6475f8089830d5ddb8f6c664f6792c5c98a6 Mon Sep 17 00:00:00 2001 From: Jer3myYu Date: Wed, 5 Feb 2025 12:27:06 -0500 Subject: [PATCH 12/12] fix: all Deque interface with ArrayDeque implementation to Queue interface with LinkedList implementation --- java/Graphs/MatrixInfection.java | 6 +++--- java/Graphs/Prerequisites.java | 4 ++-- java/Graphs/ShortestTransformationSequence.java | 6 +++--- .../ShortestTransformationSequenceOptimized.java | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/java/Graphs/MatrixInfection.java b/java/Graphs/MatrixInfection.java index da59afc..b0b2f5a 100644 --- a/java/Graphs/MatrixInfection.java +++ b/java/Graphs/MatrixInfection.java @@ -1,10 +1,10 @@ -import java.util.ArrayDeque; -import java.util.Deque; +import java.util.LinkedList; +import java.util.Queue; public class MatrixInfection { public int matrixInfection(int[][] matrix) { int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; - Deque queue = new ArrayDeque<>(); + Queue queue = new LinkedList<>(); int ones, seconds; ones = seconds = 0; // Count the total number of uninfected cells and add each infected diff --git a/java/Graphs/Prerequisites.java b/java/Graphs/Prerequisites.java index 537c953..9126ad0 100644 --- a/java/Graphs/Prerequisites.java +++ b/java/Graphs/Prerequisites.java @@ -1,6 +1,6 @@ -import java.util.ArrayDeque; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; @@ -18,7 +18,7 @@ public boolean prerequisites(int n, int[][] prerequisites) { graph.get(prerequisite).add(course); inDegrees[course]++; } - Queue queue = new ArrayDeque<>(); + Queue queue = new LinkedList<>(); // Add all courses with an in-degree of 0 to the queue. for (int i = 0; i < n; i++) { if (inDegrees[i] == 0) { diff --git a/java/Graphs/ShortestTransformationSequence.java b/java/Graphs/ShortestTransformationSequence.java index efdd455..635e1e9 100644 --- a/java/Graphs/ShortestTransformationSequence.java +++ b/java/Graphs/ShortestTransformationSequence.java @@ -1,7 +1,7 @@ -import java.util.ArrayDeque; -import java.util.Deque; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; import java.util.Set; public class ShortestTransformationSequence { @@ -14,7 +14,7 @@ public int shortestTransformationSequence(String start, String end, List return 1; } String lowerCaseAlphabet = "abcdefghijklmnopqrstuvwxyz"; - Deque queue = new ArrayDeque<>(); + Queue queue = new LinkedList<>(); Set visited = new HashSet<>(); queue.offer(start); visited.add(start); diff --git a/java/Graphs/ShortestTransformationSequenceOptimized.java b/java/Graphs/ShortestTransformationSequenceOptimized.java index 52929da..b4d9c00 100644 --- a/java/Graphs/ShortestTransformationSequenceOptimized.java +++ b/java/Graphs/ShortestTransformationSequenceOptimized.java @@ -1,7 +1,7 @@ -import java.util.ArrayDeque; -import java.util.Deque; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; import java.util.Set; public class ShortestTransformationSequenceOptimized { @@ -13,9 +13,9 @@ public int shortestTransformationSequenceOptimized(String start, String end, Lis if (start == end) { return 1; } - Deque startQueue = new ArrayDeque<>(); + Queue startQueue = new LinkedList<>(); Set startVisited = new HashSet<>(); - Deque endQueue = new ArrayDeque<>(); + Queue endQueue = new LinkedList<>(); Set endVisited = new HashSet<>(); startQueue.offer(start); startVisited.add(start); @@ -46,7 +46,7 @@ public int shortestTransformationSequenceOptimized(String start, String end, Lis // This function explores the next level in the level-order traversal // and checks if two searches meet. - private boolean exploreLevel(Deque queue, Set visited, Set otherVisited, Set dictionarySet) { + private boolean exploreLevel(Queue queue, Set visited, Set otherVisited, Set dictionarySet) { String lowerCaseAlphabet = "abcdefghijklmnopqrstuvwxyz"; int size = queue.size(); for (int j = 0; j < size; j++) {