diff --git a/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionBySize.java b/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionBySize.java
new file mode 100644
index 000000000000..71951f67dfc8
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionBySize.java
@@ -0,0 +1,83 @@
+package com.thealgorithms.datastructures.disjointsetunion;
+
+/**
+ * Disjoint Set Union (DSU) with Union by Size.
+ * This data structure tracks a set of elements partitioned into disjoint (non-overlapping) subsets.
+ * It supports two primary operations efficiently:
+ *
+ *
+ * - Find: Determine which subset a particular element belongs to.
+ * - Union: Merge two subsets into a single subset using union by size.
+ *
+ *
+ * Union by size always attaches the smaller tree under the root of the larger tree.
+ * This helps keep the tree shallow, improving the efficiency of find operations.
+ *
+ * @see Disjoint Set Union (Wikipedia)
+ */
+public class DisjointSetUnionBySize {
+ /**
+ * Node class for DSU by size.
+ * Each node keeps track of its parent and the size of the set it represents.
+ */
+ public static class Node {
+ public T value;
+ public Node parent;
+ public int size; // size of the set
+
+ public Node(T value) {
+ this.value = value;
+ this.parent = this;
+ this.size = 1; // initially, the set size is 1
+ }
+ }
+
+ /**
+ * Creates a new disjoint set containing the single specified element.
+ * @param value the element to be placed in a new singleton set
+ * @return a node representing the new set
+ */
+ public Node makeSet(final T value) {
+ return new Node<>(value);
+ }
+
+ /**
+ * Finds and returns the representative (root) of the set containing the given node.
+ * This method applies path compression to flatten the tree structure for future efficiency.
+ * @param node the node whose set representative is to be found
+ * @return the representative (root) node of the set
+ */
+ public Node findSet(Node node) {
+ if (node != node.parent) {
+ node.parent = findSet(node.parent); // path compression
+ }
+ return node.parent;
+ }
+
+ /**
+ * Merges the sets containing the two given nodes using union by size.
+ * The root of the smaller set is attached to the root of the larger set.
+ * @param x a node in the first set
+ * @param y a node in the second set
+ */
+ public void unionSets(Node x, Node y) {
+ Node rootX = findSet(x);
+ Node rootY = findSet(y);
+
+ if (rootX == rootY) {
+ return; // They are already in the same set
+ }
+ // Union by size: attach smaller tree under the larger one
+ if (rootX.size < rootY.size) {
+ rootX.parent = rootY;
+ rootY.size += rootX.size; // update size
+ } else {
+ rootY.parent = rootX;
+ rootX.size += rootY.size; // update size
+ }
+ }
+}
+// This implementation uses union by size instead of union by rank.
+// The size field tracks the number of elements in each set.
+// When two sets are merged, the smaller set is always attached to the larger set's root.
+// This helps keep the tree shallow and improves the efficiency of find operations.
diff --git a/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionBySizeTest.java b/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionBySizeTest.java
new file mode 100644
index 000000000000..71dade9796dc
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionBySizeTest.java
@@ -0,0 +1,146 @@
+package com.thealgorithms.datastructures.disjointsetunion;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.Test;
+
+public class DisjointSetUnionBySizeTest {
+
+ @Test
+ public void testMakeSet() {
+ DisjointSetUnionBySize dsu = new DisjointSetUnionBySize<>();
+ DisjointSetUnionBySize.Node node = dsu.makeSet(1);
+ assertNotNull(node);
+ assertEquals(node, node.parent);
+ assertEquals(1, node.size);
+ }
+
+ @Test
+ public void testUnionFindSet() {
+ DisjointSetUnionBySize dsu = new DisjointSetUnionBySize<>();
+ DisjointSetUnionBySize.Node node1 = dsu.makeSet(1);
+ DisjointSetUnionBySize.Node node2 = dsu.makeSet(2);
+ DisjointSetUnionBySize.Node node3 = dsu.makeSet(3);
+ DisjointSetUnionBySize.Node node4 = dsu.makeSet(4);
+
+ dsu.unionSets(node1, node2);
+ dsu.unionSets(node3, node2);
+ dsu.unionSets(node3, node4);
+ dsu.unionSets(node1, node3);
+
+ DisjointSetUnionBySize.Node root1 = dsu.findSet(node1);
+ DisjointSetUnionBySize.Node root2 = dsu.findSet(node2);
+ DisjointSetUnionBySize.Node root3 = dsu.findSet(node3);
+ DisjointSetUnionBySize.Node root4 = dsu.findSet(node4);
+
+ assertEquals(root1, root2);
+ assertEquals(root1, root3);
+ assertEquals(root1, root4);
+ assertEquals(4, root1.size);
+ }
+
+ @Test
+ public void testFindSetOnSingleNode() {
+ DisjointSetUnionBySize dsu = new DisjointSetUnionBySize<>();
+ DisjointSetUnionBySize.Node node = dsu.makeSet("A");
+ assertEquals(node, dsu.findSet(node));
+ }
+
+ @Test
+ public void testUnionAlreadyConnectedNodes() {
+ DisjointSetUnionBySize dsu = new DisjointSetUnionBySize<>();
+ DisjointSetUnionBySize.Node node1 = dsu.makeSet(1);
+ DisjointSetUnionBySize.Node node2 = dsu.makeSet(2);
+ DisjointSetUnionBySize.Node node3 = dsu.makeSet(3);
+
+ dsu.unionSets(node1, node2);
+ dsu.unionSets(node2, node3);
+
+ // Union nodes that are already connected
+ dsu.unionSets(node1, node3);
+
+ // All should have the same root
+ DisjointSetUnionBySize.Node root = dsu.findSet(node1);
+ assertEquals(root, dsu.findSet(node2));
+ assertEquals(root, dsu.findSet(node3));
+ assertEquals(3, root.size);
+ }
+
+ @Test
+ public void testMultipleMakeSets() {
+ DisjointSetUnionBySize dsu = new DisjointSetUnionBySize<>();
+ DisjointSetUnionBySize.Node node1 = dsu.makeSet(1);
+ DisjointSetUnionBySize.Node node2 = dsu.makeSet(2);
+ DisjointSetUnionBySize.Node node3 = dsu.makeSet(3);
+
+ assertNotEquals(node1, node2);
+ assertNotEquals(node2, node3);
+ assertNotEquals(node1, node3);
+
+ assertEquals(node1, node1.parent);
+ assertEquals(node2, node2.parent);
+ assertEquals(node3, node3.parent);
+ assertEquals(1, node1.size);
+ assertEquals(1, node2.size);
+ assertEquals(1, node3.size);
+ }
+
+ @Test
+ public void testPathCompression() {
+ DisjointSetUnionBySize dsu = new DisjointSetUnionBySize<>();
+ DisjointSetUnionBySize.Node node1 = dsu.makeSet(1);
+ DisjointSetUnionBySize.Node node2 = dsu.makeSet(2);
+ DisjointSetUnionBySize.Node node3 = dsu.makeSet(3);
+
+ dsu.unionSets(node1, node2);
+ dsu.unionSets(node2, node3);
+
+ // After findSet, path compression should update parent to root directly
+ DisjointSetUnionBySize.Node root = dsu.findSet(node3);
+ assertEquals(root, node1);
+ assertEquals(node1, node3.parent);
+ assertEquals(3, root.size);
+ }
+
+ @Test
+ public void testMultipleDisjointSets() {
+ DisjointSetUnionBySize dsu = new DisjointSetUnionBySize<>();
+ DisjointSetUnionBySize.Node node1 = dsu.makeSet(1);
+ DisjointSetUnionBySize.Node node2 = dsu.makeSet(2);
+ DisjointSetUnionBySize.Node node3 = dsu.makeSet(3);
+ DisjointSetUnionBySize.Node node4 = dsu.makeSet(4);
+ DisjointSetUnionBySize.Node node5 = dsu.makeSet(5);
+ DisjointSetUnionBySize.Node node6 = dsu.makeSet(6);
+
+ // Create two separate components
+ dsu.unionSets(node1, node2);
+ dsu.unionSets(node2, node3);
+
+ dsu.unionSets(node4, node5);
+ dsu.unionSets(node5, node6);
+
+ // Verify they are separate
+ assertEquals(dsu.findSet(node1), dsu.findSet(node2));
+ assertEquals(dsu.findSet(node2), dsu.findSet(node3));
+ assertEquals(dsu.findSet(node4), dsu.findSet(node5));
+ assertEquals(dsu.findSet(node5), dsu.findSet(node6));
+
+ assertNotEquals(dsu.findSet(node1), dsu.findSet(node4));
+ assertNotEquals(dsu.findSet(node3), dsu.findSet(node6));
+ }
+
+ @Test
+ public void testEmptyValues() {
+ DisjointSetUnionBySize dsu = new DisjointSetUnionBySize<>();
+ DisjointSetUnionBySize.Node emptyNode = dsu.makeSet("");
+ DisjointSetUnionBySize.Node nullNode = dsu.makeSet(null);
+
+ assertEquals(emptyNode, dsu.findSet(emptyNode));
+ assertEquals(nullNode, dsu.findSet(nullNode));
+
+ dsu.unionSets(emptyNode, nullNode);
+ assertEquals(dsu.findSet(emptyNode), dsu.findSet(nullNode));
+ }
+}