From a8ef94149acceaaaf5143b234ef9c89c766fd30c Mon Sep 17 00:00:00 2001 From: Ahmed Allam <60698204+AllamF5J@users.noreply.github.com> Date: Fri, 9 Jan 2026 02:48:38 +0200 Subject: [PATCH 01/10] feat: implement Smooth Sort algorithm with detailed JavaDoc and test class --- .../com/thealgorithms/sorts/SmoothSort.java | 173 ++++++++++++++++++ .../thealgorithms/sorts/SmoothSortTest.java | 8 + 2 files changed, 181 insertions(+) create mode 100644 src/main/java/com/thealgorithms/sorts/SmoothSort.java create mode 100644 src/test/java/com/thealgorithms/sorts/SmoothSortTest.java diff --git a/src/main/java/com/thealgorithms/sorts/SmoothSort.java b/src/main/java/com/thealgorithms/sorts/SmoothSort.java new file mode 100644 index 000000000000..7e881e84ee62 --- /dev/null +++ b/src/main/java/com/thealgorithms/sorts/SmoothSort.java @@ -0,0 +1,173 @@ +package com.thealgorithms.sorts; + +/** + * Smooth Sort is an in-place, comparison-based sorting algorithm proposed by Edsger W. Dijkstra (1981). + * + *
It can be viewed as a variant of heapsort that maintains a forest of heap-ordered Leonardo trees + * (trees whose sizes are Leonardo numbers). The algorithm is adaptive: when the input is already + * sorted or nearly sorted, the heap invariants are often satisfied and the expensive rebalancing + * operations do little work, yielding near-linear behavior. + * + *
Time Complexity: + *
Space Complexity: O(1) auxiliary space (in-place).
+ *
+ * @see Smoothsort
+ * @see Leonardo numbers
+ * @see SortAlgorithm
+ */
+public class SmoothSort implements SortAlgorithm {
+
+ /**
+ * Leonardo numbers (L(0) = L(1) = 1, L(k+2) = L(k+1) + L(k) + 1) up to the largest value that
+ * fits into a signed 32-bit integer.
+ */
+ private static final int[] LEONARDO = {
+ 1, 1, 3, 5, 9, 15, 25, 41, 67, 109,
+ 177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529,
+ 21891, 35421, 57313, 92735, 150049, 242785, 392835, 635621, 1028457, 1664079,
+ 2692537, 4356617, 7049155, 11405773, 18454929, 29860703, 48315633, 78176337, 126491971, 204668309,
+ 331160281, 535828591, 866988873, 1402817465
+ };
+
+ /**
+ * Sorts the given array in ascending order using Smooth Sort.
+ *
+ * @param array the array to sort
+ * @param The {@code slow} pointer advances by one node per iteration while {@code fast} advances by two.
+ * When {@code fast == null} or {@code fast.next == null}, {@code slow} points to the middle node.
+ * For even-length lists, this returns the second middle node. This method does not modify the input list. Complexity: This method does not modify the input list. Reference: https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_tortoise_and_hare Complexity: This class focuses on membership queries ("does the matrix contain the value?") for
+ * arbitrary 2D matrices. Unlike algorithms that rely on sorted rows/columns, these methods make no
+ * ordering assumptions.
+ *
+ * Reference: Linear search
+ * https://en.wikipedia.org/wiki/Linear_search
+ *
+ * Complexity
+ *
+ * This method makes no ordering assumptions and performs a linear scan.
+ *
+ * This method is null-safe:
+ *
+ * Assumptions
+ *
+ * Algorithm idea (search space reduction)
+ *
+ * Start in the top-right corner. At any position {@code (row, col)}:
+ *
+ * Each move removes an entire row or column from consideration, so the search performs at most
+ * {@code rows + cols - 1} comparisons.
+ *
+ * Reference: Saddleback search ("staircase" search)
+ * https://en.wikipedia.org/wiki/Saddleback_search
+ *
+ * Alternatives
+ *
+ * Complexity
+ *
+ * This overload is intended for object matrices and uses the provided {@code comparator}.
+ * The matrix must be rectangular (not jagged) with non-null rows.
+ *
+ * Note: If the matrix contains {@code null} elements (or {@code target} is {@code null}),
+ * the {@code comparator} must define how to order {@code null} values (for example,
+ * {@link Comparator#nullsFirst(Comparator)}).
+ *
+ * @param matrix the input rectangular matrix
+ * @param target the value to locate
+ * @param comparator comparator consistent with the matrix sort order
+ * @param Returns {@code true} if {@code target} exists in the matrix, {@code false} otherwise.
+ *
+ * @param matrix the input matrix
+ * @param target the value to locate
+ * @return whether the target exists in the matrix
+ * @throws IllegalArgumentException if the matrix is jagged or contains null rows
+ */
+ public static boolean search(final int[][] matrix, final int target) {
+ if (matrix == null || matrix.length == 0) {
+ return false;
+ }
+ if (matrix[0] == null || matrix[0].length == 0) {
+ return false;
+ }
+
+ final int rowCount = matrix.length;
+ final int colCount = matrix[0].length;
+
+ for (final int[] row : matrix) {
+ if (row == null) {
+ throw new IllegalArgumentException("Matrix must not contain null rows");
+ }
+ if (row.length != colCount) {
+ throw new IllegalArgumentException("Matrix must be rectangular (not jagged)");
+ }
+ }
+
+ int rowIndex = 0;
+ int colIndex = colCount - 1;
+
+ while (rowIndex < rowCount && colIndex >= 0) {
+ final int value = matrix[rowIndex][colIndex];
+ if (value == target) {
+ return true;
+ }
+ if (value > target) {
+ colIndex--;
+ } else {
+ rowIndex++;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/matrix/SearchMatrixTest.java b/src/test/java/com/thealgorithms/matrix/SearchMatrixTest.java
new file mode 100644
index 000000000000..e4a54cd89f86
--- /dev/null
+++ b/src/test/java/com/thealgorithms/matrix/SearchMatrixTest.java
@@ -0,0 +1,55 @@
+package com.thealgorithms.matrix;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+class SearchMatrixTest {
+
+ @Test
+ void nullMatrixReturnsFalse() {
+ assertFalse(SearchMatrix.contains(null, 1));
+ }
+
+ @Test
+ void emptyMatrixReturnsFalse() {
+ assertFalse(SearchMatrix.contains(new Integer[0][], 1));
+ }
+
+ @Test
+ void findsElementInRectangularMatrix() {
+ final Integer[][] matrix = {
+ {1, 2, 3},
+ {4, 5, 6},
+ };
+
+ assertTrue(SearchMatrix.contains(matrix, 5));
+ assertFalse(SearchMatrix.contains(matrix, 7));
+ }
+
+ @Test
+ void supportsNullTargetAndNullElements() {
+ final String[][] matrix = {
+ {"a", null},
+ {"b", "c"},
+ };
+
+ assertTrue(SearchMatrix.contains(matrix, null));
+ assertTrue(SearchMatrix.contains(matrix, "c"));
+ assertFalse(SearchMatrix.contains(matrix, "d"));
+ }
+
+ @Test
+ void supportsJaggedMatricesAndNullRows() {
+ final Integer[][] matrix = {
+ {1, 2, 3},
+ null,
+ {},
+ {4},
+ };
+
+ assertTrue(SearchMatrix.contains(matrix, 4));
+ assertFalse(SearchMatrix.contains(matrix, 5));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java b/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java
new file mode 100644
index 000000000000..342741473d44
--- /dev/null
+++ b/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java
@@ -0,0 +1,125 @@
+package com.thealgorithms.matrix;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Comparator;
+import org.junit.jupiter.api.Test;
+
+class SearchSortedMatrixTest {
+
+ @Test
+ void nullMatrixReturnsFalse() {
+ final int[][] matrix = null;
+ assertFalse(SearchSortedMatrix.search(matrix, 42));
+ }
+
+ @Test
+ void emptyMatrixReturnsFalse() {
+ assertFalse(SearchSortedMatrix.search(new int[0][], 42));
+ }
+
+ @Test
+ void emptyFirstRowReturnsFalse() {
+ assertFalse(SearchSortedMatrix.search(new int[][] {{}}, 42));
+ }
+
+ @Test
+ void findsExistingTargetInTypicalMatrix() {
+ final int[][] matrix = {
+ {1, 4, 7, 11, 15},
+ {2, 5, 8, 12, 19},
+ {3, 6, 9, 16, 22},
+ {10, 13, 14, 17, 24},
+ {18, 21, 23, 26, 30},
+ };
+
+ assertTrue(SearchSortedMatrix.search(matrix, 5));
+ assertTrue(SearchSortedMatrix.search(matrix, 30));
+ assertTrue(SearchSortedMatrix.search(matrix, 1));
+ }
+
+ @Test
+ void genericSearchFindsExistingTarget() {
+ final Integer[][] matrix = {
+ {1, 4, 7, 11, 15},
+ {2, 5, 8, 12, 19},
+ {3, 6, 9, 16, 22},
+ {10, 13, 14, 17, 24},
+ {18, 21, 23, 26, 30},
+ };
+
+ assertTrue(SearchSortedMatrix.search(matrix, 16, Comparator.naturalOrder()));
+ assertFalse(SearchSortedMatrix.search(matrix, 20, Comparator.naturalOrder()));
+ }
+
+ @Test
+ void returnsFalseWhenTargetDoesNotExist() {
+ final int[][] matrix = {
+ {1, 2, 3},
+ {4, 5, 6},
+ {7, 8, 9},
+ };
+
+ assertFalse(SearchSortedMatrix.search(matrix, 0));
+ assertFalse(SearchSortedMatrix.search(matrix, 10));
+ }
+
+ @Test
+ void worksForSingleRowMatrix() {
+ final int[][] matrix = {
+ {1, 3, 5, 7, 9},
+ };
+
+ assertTrue(SearchSortedMatrix.search(matrix, 7));
+ assertFalse(SearchSortedMatrix.search(matrix, 8));
+ }
+
+ @Test
+ void worksForSingleColumnMatrix() {
+ final int[][] matrix = {
+ {1},
+ {3},
+ {5},
+ {7},
+ };
+
+ assertTrue(SearchSortedMatrix.search(matrix, 1));
+ assertTrue(SearchSortedMatrix.search(matrix, 7));
+ assertFalse(SearchSortedMatrix.search(matrix, 2));
+ }
+
+ @Test
+ void handlesNegativesAndDuplicates() {
+ final int[][] matrix = {
+ {-5, -3, -3, 0},
+ {-4, -2, 1, 2},
+ {-1, 3, 3, 4},
+ };
+
+ assertTrue(SearchSortedMatrix.search(matrix, -3));
+ assertTrue(SearchSortedMatrix.search(matrix, 3));
+ assertFalse(SearchSortedMatrix.search(matrix, 6));
+ }
+
+ @Test
+ void rejectsJaggedMatrix() {
+ final int[][] jagged = {
+ {1, 2, 3},
+ {4, 5},
+ };
+
+ assertThrows(IllegalArgumentException.class, () -> SearchSortedMatrix.search(jagged, 5));
+ }
+
+ @Test
+ void rejectsNullRow() {
+ final int[][] hasNullRow = {
+ {1, 2, 3},
+ null,
+ };
+
+ assertThrows(IllegalArgumentException.class, () -> SearchSortedMatrix.search(hasNullRow, 2));
+ }
+}
From c2335673414fba6dbfa506219dd9ae8962e8893a Mon Sep 17 00:00:00 2001
From: Ahmed Allam <60698204+AllamF5J@users.noreply.github.com>
Date: Sat, 17 Jan 2026 09:21:16 +0200
Subject: [PATCH 08/10] test: add generic search tests for null and empty
matrices, jagged arrays, and null comparator
---
.../matrix/SearchSortedMatrixTest.java | 49 +++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java b/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java
index 342741473d44..203310e63b27 100644
--- a/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java
+++ b/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java
@@ -54,6 +54,55 @@ void genericSearchFindsExistingTarget() {
assertFalse(SearchSortedMatrix.search(matrix, 20, Comparator.naturalOrder()));
}
+ @Test
+ void genericNullMatrixReturnsFalse() {
+ assertFalse(SearchSortedMatrix.search((Integer[][]) null, 42, Comparator.naturalOrder()));
+ }
+
+ @Test
+ void genericEmptyMatrixReturnsFalse() {
+ assertFalse(SearchSortedMatrix.search(new Integer[0][], 42, Comparator.naturalOrder()));
+ }
+
+ @Test
+ void genericEmptyFirstRowReturnsFalse() {
+ assertFalse(SearchSortedMatrix.search(new Integer[][] {{}}, 42, Comparator.naturalOrder()));
+ }
+
+ @Test
+ void genericNullFirstRowReturnsFalse() {
+ assertFalse(SearchSortedMatrix.search(new Integer[][] {null}, 42, Comparator.naturalOrder()));
+ }
+
+ @Test
+ void genericRejectsJaggedMatrix() {
+ final Integer[][] jagged = {
+ {1, 2, 3},
+ {4, 5},
+ };
+
+ assertThrows(IllegalArgumentException.class, () -> SearchSortedMatrix.search(jagged, 5, Comparator.naturalOrder()));
+ }
+
+ @Test
+ void genericRejectsNullRow() {
+ final Integer[][] hasNullRow = {
+ {1, 2, 3},
+ null,
+ };
+
+ assertThrows(IllegalArgumentException.class, () -> SearchSortedMatrix.search(hasNullRow, 2, Comparator.naturalOrder()));
+ }
+
+ @Test
+ void genericNullComparatorThrows() {
+ final Integer[][] matrix = {
+ {1, 2, 3},
+ };
+
+ assertThrows(NullPointerException.class, () -> SearchSortedMatrix.search(matrix, 2, null));
+ }
+
@Test
void returnsFalseWhenTargetDoesNotExist() {
final int[][] matrix = {
From 3367582d0aa149c20d80ce870f0219677f3c2553 Mon Sep 17 00:00:00 2001
From: Ahmed Allam <60698204+AllamF5J@users.noreply.github.com>
Date: Sat, 17 Jan 2026 09:40:55 +0200
Subject: [PATCH 09/10] test: increase SearchSortedMatrix coverage
---
.../matrix/SearchSortedMatrixTest.java | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java b/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java
index 203310e63b27..d6f7045778f5 100644
--- a/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java
+++ b/src/test/java/com/thealgorithms/matrix/SearchSortedMatrixTest.java
@@ -25,6 +25,11 @@ void emptyFirstRowReturnsFalse() {
assertFalse(SearchSortedMatrix.search(new int[][] {{}}, 42));
}
+ @Test
+ void nullFirstRowReturnsFalse() {
+ assertFalse(SearchSortedMatrix.search(new int[][] {null}, 42));
+ }
+
@Test
void findsExistingTargetInTypicalMatrix() {
final int[][] matrix = {
@@ -40,6 +45,16 @@ void findsExistingTargetInTypicalMatrix() {
assertTrue(SearchSortedMatrix.search(matrix, 1));
}
+ @Test
+ void intSearchCoversAllComparisonBranches() {
+ final int[][] matrix = {
+ {1, 4},
+ {2, 5},
+ };
+
+ assertTrue(SearchSortedMatrix.search(matrix, 2));
+ }
+
@Test
void genericSearchFindsExistingTarget() {
final Integer[][] matrix = {
@@ -54,6 +69,16 @@ void genericSearchFindsExistingTarget() {
assertFalse(SearchSortedMatrix.search(matrix, 20, Comparator.naturalOrder()));
}
+ @Test
+ void genericSearchCoversAllComparisonBranches() {
+ final Integer[][] matrix = {
+ {1, 4},
+ {2, 5},
+ };
+
+ assertTrue(SearchSortedMatrix.search(matrix, 2, Comparator.naturalOrder()));
+ }
+
@Test
void genericNullMatrixReturnsFalse() {
assertFalse(SearchSortedMatrix.search((Integer[][]) null, 42, Comparator.naturalOrder()));
From 6d18a938706b55ffdc69f78d6009791fceaf50af Mon Sep 17 00:00:00 2001
From: Ahmed Allam <60698204+AllamF5J@users.noreply.github.com>
Date: Sun, 18 Jan 2026 07:59:57 +0200
Subject: [PATCH 10/10] refactor: simplify SearchSortedMatrix loop guards
---
.../matrix/SearchSortedMatrix.java | 30 +++++++++++++++----
.../matrix/SearchSortedMatrixTest.java | 10 +++++++
2 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/src/main/java/com/thealgorithms/matrix/SearchSortedMatrix.java b/src/main/java/com/thealgorithms/matrix/SearchSortedMatrix.java
index b227a4f0720e..bed29a6817f5 100644
--- a/src/main/java/com/thealgorithms/matrix/SearchSortedMatrix.java
+++ b/src/main/java/com/thealgorithms/matrix/SearchSortedMatrix.java
@@ -69,10 +69,16 @@ private SearchSortedMatrix() {
* @throws NullPointerException if {@code comparator} is null
*/
public static
+ *
+ */
+public final class MiddleOfLinkedList {
+
+ private MiddleOfLinkedList() {
+ }
+
+ /**
+ * Returns the middle node of the list.
+ *
+ * @param head the head of the singly linked list; may be {@code null}
+ * @return the middle node (second middle for even-sized lists), or {@code null} if {@code head} is {@code null}
+ */
+ public static SinglyLinkedListNode middleNode(final SinglyLinkedListNode head) {
+ if (head == null) {
+ return null;
+ }
+
+ SinglyLinkedListNode slow = head;
+ SinglyLinkedListNode fast = head;
+
+ while (fast != null && fast.next != null) {
+ slow = slow.next;
+ fast = fast.next.next;
+ }
+
+ return slow;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/lists/MiddleOfLinkedListTest.java b/src/test/java/com/thealgorithms/datastructures/lists/MiddleOfLinkedListTest.java
new file mode 100644
index 000000000000..b4f1a48a6ceb
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/lists/MiddleOfLinkedListTest.java
@@ -0,0 +1,71 @@
+package com.thealgorithms.datastructures.lists;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.Test;
+
+public class MiddleOfLinkedListTest {
+
+ private static SinglyLinkedListNode listOf(int... values) {
+ if (values == null || values.length == 0) {
+ return null;
+ }
+
+ SinglyLinkedListNode head = new SinglyLinkedListNode(values[0]);
+ SinglyLinkedListNode current = head;
+ for (int i = 1; i < values.length; i++) {
+ current.next = new SinglyLinkedListNode(values[i]);
+ current = current.next;
+ }
+ return head;
+ }
+
+ @Test
+ void middleNodeOddLength() {
+ SinglyLinkedListNode head = listOf(1, 2, 3, 4, 5);
+ assertEquals(3, MiddleOfLinkedList.middleNode(head).value);
+ }
+
+ @Test
+ void middleNodeEvenLengthReturnsSecondMiddle() {
+ SinglyLinkedListNode head = listOf(1, 2, 3, 4, 5, 6);
+ assertEquals(4, MiddleOfLinkedList.middleNode(head).value);
+ }
+
+ @Test
+ void middleNodeSingleElement() {
+ SinglyLinkedListNode head = listOf(42);
+ assertEquals(42, MiddleOfLinkedList.middleNode(head).value);
+ }
+
+ @Test
+ void middleNodeTwoElementsReturnsSecond() {
+ SinglyLinkedListNode head = listOf(10, 20);
+ assertEquals(20, MiddleOfLinkedList.middleNode(head).value);
+ }
+
+ @Test
+ void middleNodeNullHead() {
+ assertNull(MiddleOfLinkedList.middleNode(null));
+ }
+
+ @Test
+ void middleNodeDoesNotModifyListStructure() {
+ SinglyLinkedListNode first = new SinglyLinkedListNode(1);
+ SinglyLinkedListNode second = new SinglyLinkedListNode(2);
+ SinglyLinkedListNode third = new SinglyLinkedListNode(3);
+ SinglyLinkedListNode fourth = new SinglyLinkedListNode(4);
+
+ first.next = second;
+ second.next = third;
+ third.next = fourth;
+
+ assertEquals(3, MiddleOfLinkedList.middleNode(first).value);
+
+ assertEquals(second, first.next);
+ assertEquals(third, second.next);
+ assertEquals(fourth, third.next);
+ assertNull(fourth.next);
+ }
+}
From d46a06544ae83597fd716adc64e6098e2234432b Mon Sep 17 00:00:00 2001
From: Ahmed Allam <60698204+AllamF5J@users.noreply.github.com>
Date: Fri, 16 Jan 2026 10:48:27 +0200
Subject: [PATCH 04/10] docs: update documentation for MiddleOfLinkedList class
---
.../thealgorithms/datastructures/lists/MiddleOfLinkedList.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/MiddleOfLinkedList.java b/src/main/java/com/thealgorithms/datastructures/lists/MiddleOfLinkedList.java
index d4c5775e93f2..0ee788db2ff9 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/MiddleOfLinkedList.java
+++ b/src/main/java/com/thealgorithms/datastructures/lists/MiddleOfLinkedList.java
@@ -9,6 +9,8 @@
*
*
*
+ *
+ */
+public final class SearchMatrix {
+
+ private SearchMatrix() {
+ }
+
+ /**
+ * Searches for {@code target} in any 2D object matrix.
+ *
+ *
+ *
+ *
+ * @param matrix the input matrix (may be jagged)
+ * @param target the element to find (may be {@code null})
+ * @param
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+public final class SearchSortedMatrix {
+
+ private SearchSortedMatrix() {
+ }
+
+ /**
+ * Searches a matrix that is sorted ascending by row and by column.
+ *
+ *