From 768b5a2279847b5351f9ea22e53ffd7aefb6d54a Mon Sep 17 00:00:00 2001 From: prasanth-30011 Date: Fri, 21 Nov 2025 11:45:52 +0530 Subject: [PATCH 1/3] Add Sudoku solver using backtracking with tests --- .../backtracking/SudokuSolver.java | 121 ++++-------------- 1 file changed, 27 insertions(+), 94 deletions(-) diff --git a/src/main/java/com/thealgorithms/backtracking/SudokuSolver.java b/src/main/java/com/thealgorithms/backtracking/SudokuSolver.java index 543fe2d02b50..fdd58306a015 100644 --- a/src/main/java/com/thealgorithms/backtracking/SudokuSolver.java +++ b/src/main/java/com/thealgorithms/backtracking/SudokuSolver.java @@ -1,10 +1,10 @@ package com.thealgorithms.backtracking; /** - * Sudoku Solver using Backtracking Algorithm - * Solves a 9x9 Sudoku puzzle by filling empty cells with valid digits (1-9) + * Sudoku Solver using Backtracking Algorithm. + * Solves a 9x9 Sudoku puzzle by filling empty cells with valid digits (1-9). * - * @author Navadeep0007 + * @author prasanth-30011 */ public final class SudokuSolver { @@ -13,14 +13,14 @@ public final class SudokuSolver { private static final int EMPTY_CELL = 0; private SudokuSolver() { - // Utility class, prevent instantiation + // Prevent instantiation } /** - * Solves the Sudoku puzzle using backtracking + * Public method to solve a Sudoku puzzle. * - * @param board 9x9 Sudoku board with 0 representing empty cells - * @return true if puzzle is solved, false otherwise + * @param board 9x9 Sudoku grid (0 means empty) + * @return true if solved, false otherwise */ public static boolean solveSudoku(int[][] board) { if (board == null || board.length != GRID_SIZE) { @@ -37,15 +37,16 @@ public static boolean solveSudoku(int[][] board) { } /** - * Recursive helper method to solve the Sudoku puzzle + * Recursive helper that applies backtracking. * - * @param board the Sudoku board - * @return true if solution is found, false otherwise + * @param board Sudoku board + * @return true if solved, false otherwise */ private static boolean solve(int[][] board) { for (int row = 0; row < GRID_SIZE; row++) { for (int col = 0; col < GRID_SIZE; col++) { if (board[row][col] == EMPTY_CELL) { + for (int number = 1; number <= GRID_SIZE; number++) { if (isValidPlacement(board, row, col, number)) { board[row][col] = number; @@ -54,104 +55,36 @@ private static boolean solve(int[][] board) { return true; } - // Backtrack - board[row][col] = EMPTY_CELL; + board[row][col] = EMPTY_CELL; // Backtrack } } - return false; + + return false; // No number fits here } } } - return true; + return true; // Solved completely } - /** - * Checks if placing a number at given position is valid - * - * @param board the Sudoku board - * @param row row index - * @param col column index - * @param number number to place (1-9) - * @return true if placement is valid, false otherwise - */ private static boolean isValidPlacement(int[][] board, int row, int col, int number) { - return !isNumberInRow(board, row, number) && !isNumberInColumn(board, col, number) && !isNumberInSubgrid(board, row, col, number); - } - - /** - * Checks if number exists in the given row - * - * @param board the Sudoku board - * @param row row index - * @param number number to check - * @return true if number exists in row, false otherwise - */ - private static boolean isNumberInRow(int[][] board, int row, int number) { - for (int col = 0; col < GRID_SIZE; col++) { - if (board[row][col] == number) { - return true; - } - } - return false; - } - - /** - * Checks if number exists in the given column - * - * @param board the Sudoku board - * @param col column index - * @param number number to check - * @return true if number exists in column, false otherwise - */ - private static boolean isNumberInColumn(int[][] board, int col, int number) { - for (int row = 0; row < GRID_SIZE; row++) { - if (board[row][col] == number) { - return true; + // Row and column check + for (int i = 0; i < GRID_SIZE; i++) { + if (board[row][i] == number || board[i][col] == number) { + return false; } } - return false; - } - - /** - * Checks if number exists in the 3x3 subgrid - * - * @param board the Sudoku board - * @param row row index - * @param col column index - * @param number number to check - * @return true if number exists in subgrid, false otherwise - */ - private static boolean isNumberInSubgrid(int[][] board, int row, int col, int number) { - int subgridRowStart = row - row % SUBGRID_SIZE; - int subgridColStart = col - col % SUBGRID_SIZE; + // Subgrid check + int startRow = (row / SUBGRID_SIZE) * SUBGRID_SIZE; + int startCol = (col / SUBGRID_SIZE) * SUBGRID_SIZE; - for (int i = subgridRowStart; i < subgridRowStart + SUBGRID_SIZE; i++) { - for (int j = subgridColStart; j < subgridColStart + SUBGRID_SIZE; j++) { - if (board[i][j] == number) { - return true; + for (int r = 0; r < SUBGRID_SIZE; r++) { + for (int c = 0; c < SUBGRID_SIZE; c++) { + if (board[startRow + r][startCol + c] == number) { + return false; } } } - return false; - } - /** - * Prints the Sudoku board - * - * @param board the Sudoku board - */ - public static void printBoard(int[][] board) { - for (int row = 0; row < GRID_SIZE; row++) { - if (row % SUBGRID_SIZE == 0 && row != 0) { - System.out.println("-----------"); - } - for (int col = 0; col < GRID_SIZE; col++) { - if (col % SUBGRID_SIZE == 0 && col != 0) { - System.out.print("|"); - } - System.out.print(board[row][col]); - } - System.out.println(); - } + return true; } } From bf8b2d39a22c4ff751336b4c651aee944480fa3f Mon Sep 17 00:00:00 2001 From: prasanth-30011 Date: Fri, 21 Nov 2025 12:04:52 +0530 Subject: [PATCH 2/3] Add Kruskal's algorithm for MST using union-find --- .../greedyalgorithms/KruskalMST.java | 108 ++++++++++++++++++ .../greedyalgorithms/KruskalMSTTest.java | 37 ++++++ 2 files changed, 145 insertions(+) create mode 100644 src/main/java/com/thealgorithms/greedyalgorithms/KruskalMST.java create mode 100644 src/test/java/com/thealgorithms/greedyalgorithms/KruskalMSTTest.java diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/KruskalMST.java b/src/main/java/com/thealgorithms/greedyalgorithms/KruskalMST.java new file mode 100644 index 000000000000..3ee7ed4ece25 --- /dev/null +++ b/src/main/java/com/thealgorithms/greedyalgorithms/KruskalMST.java @@ -0,0 +1,108 @@ +package com.thealgorithms.greedyalgorithms; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Kruskal's algorithm for Minimum Spanning Tree (MST). + * Uses Disjoint Set Union (Union-Find). + * + * @author prasanth-30011 + */ +public final class KruskalMST { + + private KruskalMST() { + // utility class + } + + public static class Edge implements Comparable { + public final int u; + public final int v; + public final int weight; + + public Edge(int u, int v, int weight) { + this.u = u; + this.v = v; + this.weight = weight; + } + + @Override + public int compareTo(Edge other) { + return Integer.compare(this.weight, other.weight); + } + } + + private static class DSU { + private final int[] parent; + private final int[] rank; + + DSU(int n) { + parent = new int[n]; + rank = new int[n]; + for (int i = 0; i < n; i++) { + parent[i] = i; + rank[i] = 0; + } + } + + int find(int x) { + if (parent[x] != x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + boolean union(int x, int y) { + int rx = find(x); + int ry = find(y); + if (rx == ry) { + return false; + } + if (rank[rx] < rank[ry]) { + parent[rx] = ry; + } else if (rank[rx] > rank[ry]) { + parent[ry] = rx; + } else { + parent[ry] = rx; + rank[rx]++; + } + return true; + } + } + + /** + * Computes the total weight of a Minimum Spanning Tree. + * + * @param n number of vertices (0..n-1) + * @param edges list of edges + * @return total MST weight, or -1 if graph is disconnected + */ + public static int minimumSpanningTreeWeight(int n, List edges) { + if (n <= 0) { + throw new IllegalArgumentException("Number of vertices must be positive"); + } + + List sortedEdges = new ArrayList<>(edges); + Collections.sort(sortedEdges); + + DSU dsu = new DSU(n); + int mstWeight = 0; + int edgesUsed = 0; + + for (Edge e : sortedEdges) { + if (dsu.union(e.u, e.v)) { + mstWeight += e.weight; + edgesUsed++; + if (edgesUsed == n - 1) { + break; + } + } + } + + if (edgesUsed != n - 1) { + return -1; // graph not connected + } + return mstWeight; + } +} diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/KruskalMSTTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/KruskalMSTTest.java new file mode 100644 index 000000000000..e0bf5ac58c1a --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/KruskalMSTTest.java @@ -0,0 +1,37 @@ +package com.thealgorithms.greedyalgorithms; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import org.junit.jupiter.api.Test; + +class KruskalMSTTest { + + @Test + void testSimpleConnectedGraph() { + int n = 4; + List edges = List.of( + new KruskalMST.Edge(0, 1, 10), + new KruskalMST.Edge(0, 2, 6), + new KruskalMST.Edge(0, 3, 5), + new KruskalMST.Edge(1, 3, 15), + new KruskalMST.Edge(2, 3, 4) + ); + + int mstWeight = KruskalMST.minimumSpanningTreeWeight(n, edges); + // Known MST: edges (2-3, 0-3, 0-1) = 4 + 5 + 10 = 19 + assertEquals(19, mstWeight); + } + + @Test + void testDisconnectedGraph() { + int n = 4; + List edges = List.of( + new KruskalMST.Edge(0, 1, 3), + new KruskalMST.Edge(2, 3, 5) + ); + + int mstWeight = KruskalMST.minimumSpanningTreeWeight(n, edges); + assertEquals(-1, mstWeight); + } +} From 02f4f2371fd60178b399808c75b5e3f3b2632cc3 Mon Sep 17 00:00:00 2001 From: prasanth-30011 Date: Wed, 26 Nov 2025 00:13:06 +0530 Subject: [PATCH 3/3] Add Dijkstra algorithm implementation (Fixes #7112) --- graphs/Dijkstra.java | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 graphs/Dijkstra.java diff --git a/graphs/Dijkstra.java b/graphs/Dijkstra.java new file mode 100644 index 000000000000..0e79892f7bad --- /dev/null +++ b/graphs/Dijkstra.java @@ -0,0 +1,41 @@ +package com.thealgorithms.graphs; + +import java.util.*; + +public class Dijkstra { + + public static int[] dijkstra(List> graph, int source) { + int n = graph.size(); + int[] dist = new int[n]; + Arrays.fill(dist, Integer.MAX_VALUE); + dist[source] = 0; + + PriorityQueue pq = + new PriorityQueue<>(Comparator.comparingInt(a -> a[1])); + + pq.offer(new int[]{source, 0}); + + while (!pq.isEmpty()) { + int[] curr = pq.poll(); + int u = curr[0]; + int d = curr[1]; + + if (d > dist[u]) continue; + + for (int[] edge : graph.get(u)) { + int v = edge[0]; + int w = edge[1]; + + if (w < 0) { + throw new IllegalArgumentException("Negative weight detected"); + } + + if (dist[u] + w < dist[v]) { + dist[v] = dist[u] + w; + pq.offer(new int[]{v, dist[v]}); + } + } + } + return dist; + } +}