diff --git a/.github/workflows/update-directorymd.yml b/.github/workflows/update-directorymd.yml
index 101d82427e38..1cfee6e36e4e 100644
--- a/.github/workflows/update-directorymd.yml
+++ b/.github/workflows/update-directorymd.yml
@@ -33,7 +33,7 @@ jobs:
git diff --cached --quiet || git commit -m "Update DIRECTORY.md"
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v7
+ uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.REPO_SCOPED_TOKEN }}
branch: update-directory
diff --git a/DIRECTORY.md b/DIRECTORY.md
index deaf59636fa4..585c634c3429 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -626,8 +626,6 @@
- π [SkylineProblem](src/main/java/com/thealgorithms/others/SkylineProblem.java)
- π [TwoPointers](src/main/java/com/thealgorithms/others/TwoPointers.java)
- π [Verhoeff](src/main/java/com/thealgorithms/others/Verhoeff.java)
- - π **cn**
- - π [HammingDistance](src/main/java/com/thealgorithms/others/cn/HammingDistance.java)
- π **physics**
- π [CoulombsLaw](src/main/java/com/thealgorithms/physics/CoulombsLaw.java)
- π [DampedOscillator](src/main/java/com/thealgorithms/physics/DampedOscillator.java)
@@ -701,7 +699,6 @@
- π [LowerBound](src/main/java/com/thealgorithms/searches/LowerBound.java)
- π [MonteCarloTreeSearch](src/main/java/com/thealgorithms/searches/MonteCarloTreeSearch.java)
- π [OrderAgnosticBinarySearch](src/main/java/com/thealgorithms/searches/OrderAgnosticBinarySearch.java)
- - π [PerfectBinarySearch](src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java)
- π [QuickSelect](src/main/java/com/thealgorithms/searches/QuickSelect.java)
- π [RabinKarpAlgorithm](src/main/java/com/thealgorithms/searches/RabinKarpAlgorithm.java)
- π [RandomSearch](src/main/java/com/thealgorithms/searches/RandomSearch.java)
@@ -710,7 +707,6 @@
- π [SaddlebackSearch](src/main/java/com/thealgorithms/searches/SaddlebackSearch.java)
- π [SearchInARowAndColWiseSortedMatrix](src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java)
- π [SentinelLinearSearch](src/main/java/com/thealgorithms/searches/SentinelLinearSearch.java)
- - π [SortOrderAgnosticBinarySearch](src/main/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearch.java)
- π [SquareRootBinarySearch](src/main/java/com/thealgorithms/searches/SquareRootBinarySearch.java)
- π [TernarySearch](src/main/java/com/thealgorithms/searches/TernarySearch.java)
- π [UnionFind](src/main/java/com/thealgorithms/searches/UnionFind.java)
@@ -817,7 +813,6 @@
- π [LetterCombinationsOfPhoneNumber](src/main/java/com/thealgorithms/strings/LetterCombinationsOfPhoneNumber.java)
- π [LongestCommonPrefix](src/main/java/com/thealgorithms/strings/LongestCommonPrefix.java)
- π [LongestNonRepetitiveSubstring](src/main/java/com/thealgorithms/strings/LongestNonRepetitiveSubstring.java)
- - π [LongestPalindromicSubstring](src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java)
- π [Lower](src/main/java/com/thealgorithms/strings/Lower.java)
- π [Manacher](src/main/java/com/thealgorithms/strings/Manacher.java)
- π [MyAtoi](src/main/java/com/thealgorithms/strings/MyAtoi.java)
@@ -834,7 +829,6 @@
- π [StringMatchFiniteAutomata](src/main/java/com/thealgorithms/strings/StringMatchFiniteAutomata.java)
- π [SuffixArray](src/main/java/com/thealgorithms/strings/SuffixArray.java)
- π [Upper](src/main/java/com/thealgorithms/strings/Upper.java)
- - π [ValidParentheses](src/main/java/com/thealgorithms/strings/ValidParentheses.java)
- π [WordLadder](src/main/java/com/thealgorithms/strings/WordLadder.java)
- π [ZAlgorithm](src/main/java/com/thealgorithms/strings/ZAlgorithm.java)
- π **zigZagPattern**
@@ -1395,7 +1389,6 @@
- π [MaximumSumOfDistinctSubarraysWithLengthKTest](src/test/java/com/thealgorithms/others/MaximumSumOfDistinctSubarraysWithLengthKTest.java)
- π [MiniMaxAlgorithmTest](src/test/java/com/thealgorithms/others/MiniMaxAlgorithmTest.java)
- π [MosAlgorithmTest](src/test/java/com/thealgorithms/others/MosAlgorithmTest.java)
- - π [NewManShanksPrimeTest](src/test/java/com/thealgorithms/others/NewManShanksPrimeTest.java)
- π [NextFitTest](src/test/java/com/thealgorithms/others/NextFitTest.java)
- π [PageRankTest](src/test/java/com/thealgorithms/others/PageRankTest.java)
- π [PasswordGenTest](src/test/java/com/thealgorithms/others/PasswordGenTest.java)
@@ -1404,8 +1397,6 @@
- π [SkylineProblemTest](src/test/java/com/thealgorithms/others/SkylineProblemTest.java)
- π [TwoPointersTest](src/test/java/com/thealgorithms/others/TwoPointersTest.java)
- π [WorstFitCPUTest](src/test/java/com/thealgorithms/others/WorstFitCPUTest.java)
- - π **cn**
- - π [HammingDistanceTest](src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java)
- π **physics**
- π [CoulombsLawTest](src/test/java/com/thealgorithms/physics/CoulombsLawTest.java)
- π [DampedOscillatorTest](src/test/java/com/thealgorithms/physics/DampedOscillatorTest.java)
@@ -1479,7 +1470,6 @@
- π [LowerBoundTest](src/test/java/com/thealgorithms/searches/LowerBoundTest.java)
- π [MonteCarloTreeSearchTest](src/test/java/com/thealgorithms/searches/MonteCarloTreeSearchTest.java)
- π [OrderAgnosticBinarySearchTest](src/test/java/com/thealgorithms/searches/OrderAgnosticBinarySearchTest.java)
- - π [PerfectBinarySearchTest](src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java)
- π [QuickSelectTest](src/test/java/com/thealgorithms/searches/QuickSelectTest.java)
- π [RabinKarpAlgorithmTest](src/test/java/com/thealgorithms/searches/RabinKarpAlgorithmTest.java)
- π [RandomSearchTest](src/test/java/com/thealgorithms/searches/RandomSearchTest.java)
@@ -1488,7 +1478,6 @@
- π [SaddlebackSearchTest](src/test/java/com/thealgorithms/searches/SaddlebackSearchTest.java)
- π [SearchInARowAndColWiseSortedMatrixTest](src/test/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrixTest.java)
- π [SentinelLinearSearchTest](src/test/java/com/thealgorithms/searches/SentinelLinearSearchTest.java)
- - π [SortOrderAgnosticBinarySearchTest](src/test/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearchTest.java)
- π [SquareRootBinarySearchTest](src/test/java/com/thealgorithms/searches/SquareRootBinarySearchTest.java)
- π [TernarySearchTest](src/test/java/com/thealgorithms/searches/TernarySearchTest.java)
- π [TestSearchInARowAndColWiseSortedMatrix](src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java)
@@ -1593,7 +1582,6 @@
- π [LetterCombinationsOfPhoneNumberTest](src/test/java/com/thealgorithms/strings/LetterCombinationsOfPhoneNumberTest.java)
- π [LongestCommonPrefixTest](src/test/java/com/thealgorithms/strings/LongestCommonPrefixTest.java)
- π [LongestNonRepetitiveSubstringTest](src/test/java/com/thealgorithms/strings/LongestNonRepetitiveSubstringTest.java)
- - π [LongestPalindromicSubstringTest](src/test/java/com/thealgorithms/strings/LongestPalindromicSubstringTest.java)
- π [LowerTest](src/test/java/com/thealgorithms/strings/LowerTest.java)
- π [ManacherTest](src/test/java/com/thealgorithms/strings/ManacherTest.java)
- π [MyAtoiTest](src/test/java/com/thealgorithms/strings/MyAtoiTest.java)
@@ -1609,7 +1597,6 @@
- π [StringMatchFiniteAutomataTest](src/test/java/com/thealgorithms/strings/StringMatchFiniteAutomataTest.java)
- π [SuffixArrayTest](src/test/java/com/thealgorithms/strings/SuffixArrayTest.java)
- π [UpperTest](src/test/java/com/thealgorithms/strings/UpperTest.java)
- - π [ValidParenthesesTest](src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java)
- π [WordLadderTest](src/test/java/com/thealgorithms/strings/WordLadderTest.java)
- π [ZAlgorithmTest](src/test/java/com/thealgorithms/strings/ZAlgorithmTest.java)
- π **zigZagPattern**
diff --git a/README-ko.md b/README-ko.md
deleted file mode 100644
index 4f8cab92fc42..000000000000
--- a/README-ko.md
+++ /dev/null
@@ -1,191 +0,0 @@
-# μκ³ λ¦¬μ¦ - μλ°
-
-## μ΄ [κ°λ°λΈλ°μΉ](https://github.com/TheAlgorithms/Java/tree/Development)λ κΈ°μ‘΄ νλ‘μ νΈλ₯Ό Java νλ‘μ νΈ κ΅¬μ‘°λ‘ μ¬κ°λ°νκΈ° μν΄ μμ±λμλ€. κΈ°μ¬λλ₯Ό μν΄ κ°λ° μ§μ¬λ‘ μ νν μ μλ€. μμΈν λ΄μ©μ μ΄ λ¬Έμ λ₯Ό μ°Έμ‘°νμμμ€. 컨νΈλ¦¬λ·°μ
μ μν΄ [κ°λ°λΈλ°μΉ](https://github.com/TheAlgorithms/Java/tree/Development)λ‘ μ νν μ μλ€. μμΈν λ΄μ©μ [μ΄ μ΄μ](https://github.com/TheAlgorithms/Java/issues/474)λ₯Ό μ°Έκ³ νμμμ€.
-
-### μλ°λ‘ ꡬνλ λͺ¨λ μκ³ λ¦¬μ¦λ€ (κ΅μ‘μ©)
-
-μ΄κ²λ€μ λ¨μ§ μλ²μ μν κ²μ΄λ€. νμ€ μλ° λΌμ΄λΈλ¬λ¦¬μλ μ±λ₯μμ μ΄μ λ‘ λ λμ κ²λ€μ΄ ꡬνλμ΄μλ€
-
-## μ λ ¬ μκ³ λ¦¬μ¦
-
-### Bubble(λ²λΈ μ λ ¬)
-
-![alt text][bubble-image]
-
-From [Wikipedia][bubble-wiki]: λ²λΈ μνΈ(sinking sorλΌκ³ λ λΆλ¦¬μ)λ 리μ€νΈλ₯Ό λ°λ³΅μ μΈ λ¨κ³λ‘ μ κ·Όνμ¬ μ λ ¬νλ€. κ°κ°μ μ§μ λΉκ΅νλ©°, μμκ° μλͺ»λ κ²½μ° κ·Έμ ν μμ΄ν
λ€μ μ€μνλ μκ³ λ¦¬μ¦μ΄λ€. λ μ΄μ μ€μν κ²μ΄ μμ λκΉμ§ λ°λ³΅νλ©°, λ°λ³΅μ΄ λλ¨μ 리μ€νΈκ° μ λ ¬λμμμ μλ―Ένλ€.
-
-**μμ±**
-
-- μ΅μ
μ μ±λ₯ O(n^2)
-- μ΅κ³ μ μ±λ₯ O(n)
-- νκ· μ±λ₯ O(n^2)
-
-###### View the algorithm in [action][bubble-toptal]
-
-### Insertion(μ½μ
μ λ ¬)
-
-![alt text][insertion-image]
-
-From [Wikipedia][insertion-wiki]: μ½μ
μ λ ¬μ μ΅μ’
μ λ ¬λ λ°°μ΄(λλ 리μ€νΈ)μ νλ²μ νλμ© κ΅¬μΆνλ μκ³ λ¦¬μ¦μ΄λ€. μ΄κ²μ ν° λ¦¬μ€νΈμμ λ λμ μκ³ λ¦¬μ¦μΈ ν΅ μνΈ, ν μνΈ, λλ λ¨Έμ§ μνΈλ³΄λ€ ν¨μ¬ μμ’μ ν¨μ¨μ κ°μ§λ€. κ·Έλ¦Όμμ κ° λ§λλ μ λ ¬ν΄μΌ νλ λ°°μ΄μ μμλ₯Ό λνλΈλ€. μλ¨κ³Ό λ λ²μ§Έ μλ¨ λ§λμ 첫 λ²μ§Έ κ΅μ°¨μ μμ λ°μνλ κ²μ λ λ²μ§Έ μμκ° μ²« λ²μ§Έ μμλ³΄λ€ λ λμ μ°μ μμλ₯Ό κ°μ§κΈ° λλ¬Έμ λ§λλ‘ νμλλ μ΄λ¬ν μμλ₯Ό κ΅νν κ²μ΄λ€. μ΄ λ°©λ²μ λ°λ³΅νλ©΄ μ½μ
μ λ ¬μ΄ μλ£λλ€.
-
-**μμ±**
-
-- μ΅μ
μ μ±λ₯ O(n^2)
-- μ΅κ³ μ μ±λ₯ O(n)
-- νκ· O(n^2)
-
-###### View the algorithm in [action][insertion-toptal]
-
-### Merge(ν©λ³ μ λ ¬)
-
-![alt text][merge-image]
-
-From [Wikipedia][merge-wiki]: μ»΄ν¨ν° κ³Όνμμ, ν©λ³ μ λ ¬μ ν¨μ¨μ μΈ, λ²μ©μ μΈ, λΉκ΅ κΈ°λ° μ λ ¬ μκ³ λ¦¬μ¦μ΄λ€. λλΆλΆμ ꡬνμ μμ μ μΈ λΆλ₯λ₯Ό μ΄λ£¨λλ°, μ΄κ²μ ꡬνμ΄ μ λ ¬λ μΆλ ₯μ λμΌν μμμ μ
λ ₯ μμλ₯Ό μ μ§νλ€λ κ²μ μλ―Ένλ€. ν©λ³ μ λ ¬μ 1945λ
μ John von Neumannμ΄ λ°λͺ
ν λΆν μ 볡 μκ³ λ¦¬μ¦μ΄λ€.
-
-**μμ±**
-
-- μ΅μ
μ μ±λ₯ O(n log n) (μΌλ°μ )
-- μ΅κ³ μ μ±λ₯ O(n log n)
-- νκ· O(n log n)
-
-###### View the algorithm in [action][merge-toptal]
-
-### Quick(ν΅ μ λ ¬)
-
-![alt text][quick-image]
-
-From [Wikipedia][quick-wiki]: ν΅ μ λ ¬sometimes called partition-exchange sort)μ ν¨μ¨μ μΈ μ λ ¬ μκ³ λ¦¬μ¦μΌλ‘, λ°°μ΄μ μμλ₯Ό μμλλ‘ μ λ ¬νλ 체κ³μ μΈ λ°©λ² μνμ νλ€.
-
-**μμ±**
-
-- μ΅μ
μ μ±λ₯ O(n^2)
-- μ΅κ³ μ μ±λ₯ O(n log n) or O(n) with three-way partition
-- νκ· O(n log n)
-
-###### View the algorithm in [action][quick-toptal]
-
-### Selection(μ ν μ λ ¬)
-
-![alt text][selection-image]
-
-From [Wikipedia][selection-wiki]: μκ³ λ¦¬μ¦ μ
λ ₯ 리μ€νΈλ₯Ό λ λΆλΆμΌλ‘ λλλ€ : 첫 λΆλΆμ μμ΄ν
λ€μ΄ μ΄λ―Έ μΌμͺ½μμ μ€λ₯Έμͺ½μΌλ‘ μ λ ¬λμλ€. κ·Έλ¦¬κ³ λ¨μ λΆλΆμ μμ΄ν
λ€μ λλ¨Έμ§ νλͺ©μ μ°¨μ§νλ 리μ€νΈμ΄λ€. μ²μμλ μ λ ¬λ 리μ€νΈλ 곡백μ΄κ³ λλ¨Έμ§κ° μ λΆμ΄λ€. μ€λ₯΄μ°¨μ(λλ λ΄λ¦Όμ°¨μ) μκ³ λ¦¬μ¦μ κ°μ₯ μμ μμλ₯Ό μ λ ¬λμ§ μμ 리μ€νΈμμ μ°Ύκ³ μ λ ¬μ΄ μλ κ°μ₯ μΌμͺ½(μ λ ¬λ 리μ€νΈ) 리μ€νΈμ λ°κΎΌλ€. μ΄λ κ² μ€λ₯Έμͺ½μΌλ‘ λμκ°λ€.
-
-**μμ±**
-
-- μ΅μ
μ μ±λ₯ O(n^2)
-- μ΅κ³ μ μ±λ₯ O(n^2)
-- νκ· O(n^2)
-
-###### View the algorithm in [action][selection-toptal]
-
-### Shell(μ μ λ ¬)
-
-![alt text][shell-image]
-
-From [Wikipedia][shell-wiki]: μ μ λ ¬μ λ©λ¦¬ λ¨μ΄μ Έ μλ νλͺ©μ κ΅νμ νμ©νλ μ½μ
μ’
λ₯μ μΌλ°νμ΄λ€. κ·Έ μμ΄λμ΄λ λͺ¨λ nλ²μ§Έ μμκ° μ λ ¬λ λͺ©λ‘μ μ 곡νλ€λ κ²μ κ³ λ €νμ¬ μ΄λ κ³³μμλ μ§ μμνλλ‘ μμμ λͺ©λ‘μ λ°°μ΄νλ κ²μ΄λ€. μ΄λ¬ν λͺ©λ‘μ h-sortedλ‘ μλ €μ Έ μλ€. λ§μ°¬κ°μ§λ‘, κ°κ° κ°λ³μ μΌλ‘ μ λ ¬λ h μΈν°λ¦¬λΈ λͺ©λ‘μΌλ‘ κ°μ£Όν μ μλ€.
-
-**μμ±**
-
-- μ΅μ
μ μ±λ₯ O(nlog2 2n)
-- μ΅κ³ μ μ±λ₯ O(n log n)
-- Average case performance depends on gap sequence
-
-###### View the algorithm in [action][shell-toptal]
-
-### μκ° λ³΅μ‘μ± κ·Έλν
-
-μ λ ¬ μκ³ λ¦¬μ¦μ 볡μ‘μ± λΉκ΅ (λ²λΈ μ λ ¬, μ½μ
μ λ ¬, μ ν μ λ ¬)
-
-[볡μ‘μ± κ·Έλν](https://github.com/prateekiiest/Python/blob/master/sorts/sortinggraphs.png)
-
----
-
-## κ²μ μκ³ λ¦¬μ¦
-
-### Linear (μ ν νμ)
-
-![alt text][linear-image]
-
-From [Wikipedia][linear-wiki]: μ ν νμ λλ μμ°¨ νμμ λͺ©λ‘ λ΄μμ λͺ©νκ°μ μ°Ύλ λ°©λ²μ΄λ€. μΌμΉ νλͺ©μ΄ λ°κ²¬λκ±°λ λͺ¨λ μμκ° νμλ λκΉμ§ λͺ©λ‘μ κ° μμμ λν΄ λͺ©νκ°μ μμ°¨μ μΌλ‘ κ²μ¬νλ€.
-μ ν κ²μμ μ΅μ
μ μ ν μκ°μΌλ‘ μ€νλλ©° μ΅λ nκ°μ λΉκ΅μμ μ΄λ£¨μ΄μ§λ€. μ¬κΈ°μ nμ λͺ©λ‘μ κΈΈμ΄λ€.
-
-**μμ±**
-
-- μ΅μ
μ μ±λ₯ O(n)
-- μ΅κ³ μ μ±λ₯ O(1)
-- νκ· O(n)
-- μ΅μ
μ κ²½μ° κ³΅κ° λ³΅μ‘μ± O(1) iterative
-
-### Binary (μ΄μ§ νμ)
-
-![alt text][binary-image]
-
-From [Wikipedia][binary-wiki]: μ΄μ§ νμ, (also known as half-interval search or logarithmic search), μ μ λ ¬λ λ°°μ΄ λ΄μμ λͺ©νκ°μ μμΉλ₯Ό μ°Ύλ κ²μ μκ³ λ¦¬μ¦μ΄λ€. λͺ©νκ°μ λ°°μ΄μ μ€κ° μμμ λΉκ΅νλ€; λ§μ½ λͺ©νκ°μ΄ λμΌνμ§ μμΌλ©΄, λͺ©νλ¬Όμ μ λ°μ΄ μ κ±°λκ³ κ²μμ΄ μ±κ³΅ν λκΉμ§ λλ¨Έμ§ μ λ°μμ μλλ€.
-
-**μμ±**
-
-- μ΅μ
μ μ±λ₯ O(log n)
-- μ΅κ³ μ μ±λ₯ O(1)
-- νκ· O(log n)
-- μ΅μ
μ κ²½μ° κ³΅κ° λ³΅μ‘μ± O(1)
-
-[bubble-toptal]: https://www.toptal.com/developers/sorting-algorithms/bubble-sort
-[bubble-wiki]: https://en.wikipedia.org/wiki/Bubble_sort
-[bubble-image]: https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Bubblesort-edited-color.svg/220px-Bubblesort-edited-color.svg.png "Bubble Sort"
-[insertion-toptal]: https://www.toptal.com/developers/sorting-algorithms/insertion-sort
-[insertion-wiki]: https://en.wikipedia.org/wiki/Insertion_sort
-[insertion-image]: https://upload.wikimedia.org/wikipedia/commons/7/7e/Insertionsort-edited.png "Insertion Sort"
-[quick-toptal]: https://www.toptal.com/developers/sorting-algorithms/quick-sort
-[quick-wiki]: https://en.wikipedia.org/wiki/Quicksort
-[quick-image]: https://upload.wikimedia.org/wikipedia/commons/6/6a/Sorting_quicksort_anim.gif "Quick Sort"
-[merge-toptal]: https://www.toptal.com/developers/sorting-algorithms/merge-sort
-[merge-wiki]: https://en.wikipedia.org/wiki/Merge_sort
-[merge-image]: https://upload.wikimedia.org/wikipedia/commons/c/cc/Merge-sort-example-300px.gif "Merge Sort"
-[selection-toptal]: https://www.toptal.com/developers/sorting-algorithms/selection-sort
-[selection-wiki]: https://en.wikipedia.org/wiki/Selection_sort
-[selection-image]: https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Selection_sort_animation.gif/250px-Selection_sort_animation.gif "Selection Sort Sort"
-[shell-toptal]: https://www.toptal.com/developers/sorting-algorithms/shell-sort
-[shell-wiki]: https://en.wikipedia.org/wiki/Shellsort
-[shell-image]: https://upload.wikimedia.org/wikipedia/commons/d/d8/Sorting_shellsort_anim.gif "Shell Sort"
-[linear-wiki]: https://en.wikipedia.org/wiki/Linear_search
-[linear-image]: http://www.tutorialspoint.com/data_structures_algorithms/images/linear_search.gif
-[binary-wiki]: https://en.wikipedia.org/wiki/Binary_search_algorithm
-[binary-image]: https://upload.wikimedia.org/wikipedia/commons/f/f7/Binary_search_into_array.png
-
----
-
-## λλ¨Έμ§ μκ³ λ¦¬μ¦μ λν λ§ν¬
-
-| μ ν | λ€μ΄λλ―Ήνλ‘κ·Έλλ°(DP) | μνΈ | κ·Έ μΈ κ²λ€ |
-| --------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------ |
-| [Any Base to Any Base](Conversions/AnyBaseToAnyBase.java) | [Coin Change](DynamicProgramming/CoinChange.java) | [Caesar](Ciphers/Caesar.java) | [Heap Sort](Sorts/HeapSort.java) |
-| [Any Base to Decimal](Conversions/AnyBaseToDecimal.java) | [Egg Dropping](DynamicProgramming/EggDropping.java) | [Columnar Transposition Cipher](Ciphers/ColumnarTranspositionCipher.java) | [Palindromic Prime Checker](Misc/PalindromePrime.java) |
-| [Binary to Decimal](Conversions/BinaryToDecimal.java) | [Fibonacci](DynamicProgramming/Fibonacci.java) | [RSA](Ciphers/RSA.java) | More soon... |
-| [Binary to HexaDecimal](Conversions/BinaryToHexadecimal.java) | [Kadane Algorithm](DynamicProgramming/KadaneAlgorithm.java) | more coming soon... |
-| [Binary to Octal](Conversions/BinaryToOctal.java) | [Knapsack](DynamicProgramming/Knapsack.java) |
-| [Decimal To Any Base](Conversions/DecimalToAnyBase.java) | [Longest Common Subsequence](DynamicProgramming/LongestCommonSubsequence.java) |
-| [Decimal To Binary](Conversions/DecimalToBinary.java) | [Longest Increasing Subsequence](DynamicProgramming/LongestIncreasingSubsequence.java) |
-| [Decimal To Hexadecimal](Conversions/DecimalToHexaDecimal.java) | [Rod Cutting](DynamicProgramming/RodCutting.java) |
-| and much more... | and more... |
-
-### μλ£ κ΅¬μ‘°
-
-| κ·Έλν | ν | 리μ€νΈ | ν |
-| ------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------- |
-| | [λΉ ν μμΈμ²λ¦¬](DataStructures/Heaps/EmptyHeapException.java) | [μν μ°κ²°λ¦¬μ€νΈ](DataStructures/Lists/CircleLinkedList.java) | [μ λλ¦ μ΄λ μ΄ λ¦¬μ€νΈ ν](DataStructures/Queues/GenericArrayListQueue.java) |
-| | [ν](DataStructures/Heaps/Heap.java) | [μ΄μ€ μ°κ²°λ¦¬μ€νΈ](DataStructures/Lists/DoublyLinkedList.java) | [ν](DataStructures/Queues/Queues.java) |
-| [κ·Έλν](DataStructures/Graphs/Graphs.java) | [ν μμ](DataStructures/Heaps/HeapElement.java) | [λ¨μ μ°κ²°λ¦¬μ€νΈ](DataStructures/Lists/SinglyLinkedList.java) |
-| [ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦](DataStructures/Graphs/Kruskal.java) | [μ΅λν](DataStructures/Heaps/MaxHeap.java) |
-| [νλ ¬ κ·Έλν](DataStructures/Graphs/MatrixGraphs.java) | [μ΅μν](DataStructures/Heaps/MinHeap.java) |
-| [νλ¦Ό μ΅μμ μ₯νΈλ¦¬](DataStructures/Graphs/PrimMST.java) |
-
-| μ€ν | νΈλ¦¬ |
-| --------------------------------------------------------------- | ------------------------------------------------- |
-| [λ
Έλ μ€ν](DataStructures/Stacks/NodeStack.java) | [AVL νΈλ¦¬](DataStructures/Trees/AVLTree.java) |
-| [μ°κ²°λ¦¬μ€νΈ μ€ν](DataStructures/Stacks/StackOfLinkedList.java) | [μ΄μ§ νΈλ¦¬](DataStructures/Trees/BinaryTree.java) |
-| [μ€ν](DataStructures/Stacks) | And much more... |
-
-- [Bags](DataStructures/Bags/Bag.java)
-- [Buffer](DataStructures/Buffers/CircularBuffer.java)
-- [HashMap](DataStructures/HashMap/Hashing/HashMap.java)
--
diff --git a/pom.xml b/pom.xml
index 73869d6dd942..f13169cece97 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
UTF-8
21
21
- 3.27.6
+ 3.27.7
@@ -20,7 +20,7 @@
org.junit
junit-bom
- 6.0.1
+ 6.0.2
pom
import
@@ -69,7 +69,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.14.1
+ 3.15.0
21
@@ -112,7 +112,7 @@
com.puppycrawl.tools
checkstyle
- 13.0.0
+ 13.1.0
@@ -127,7 +127,7 @@
com.mebigfatguy.fb-contrib
fb-contrib
- 7.7.2
+ 7.7.4
com.h3xstream.findsecbugs
diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml
index 3e2f1ff84ca8..1390387bacdf 100644
--- a/spotbugs-exclude.xml
+++ b/spotbugs-exclude.xml
@@ -207,6 +207,12 @@
+
+
+
+
+
+
diff --git a/src/main/java/com/thealgorithms/ciphers/ElGamalCipher.java b/src/main/java/com/thealgorithms/ciphers/ElGamalCipher.java
new file mode 100644
index 000000000000..6383caa59b1f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/ElGamalCipher.java
@@ -0,0 +1,174 @@
+package com.thealgorithms.ciphers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * ElGamal Encryption Algorithm Implementation.
+ *
+ *
+ * ElGamal is an asymmetric key encryption algorithm for public-key cryptography
+ * based on the DiffieβHellman key exchange. It relies on the difficulty
+ * of computing discrete logarithms in a cyclic group.
+ *
+ *
+ *
+ * Key Features:
+ *
+ * - Uses Safe Primes (p = 2q + 1) to ensure group security.
+ * - Verifies the generator is a primitive root modulo p.
+ * - Stateless design using Java Records.
+ * - SecureRandom for all cryptographic operations.
+ *
+ *
+ *
+ * @author Chahat Sandhu, 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.
+ *
+ * Reference: https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_tortoise_and_hare
+ *
+ *
+ * This implementation uses the Bell Triangle (Aitken's array) method.
+ * Time Complexity: O(n^2)
+ * Space Complexity: O(n^2)
+ *
+ *
+ * @author Chahat Sandhu, This class provides a method to calculate the Euclidean distance between two points in a
+ * two-dimensional plane.
+ *
+ *
Reference: https://en.wikipedia.org/wiki/Euclidean_distance
+ */
+public final class DistanceBetweenTwoPoints {
+
+ private DistanceBetweenTwoPoints() {
+ // Utility class; prevent instantiation
+ }
+
+ /**
+ * Calculate the Euclidean distance between two points.
+ *
+ * @param x1 x-coordinate of the first point
+ * @param y1 y-coordinate of the first point
+ * @param x2 x-coordinate of the second point
+ * @param y2 y-coordinate of the second point
+ * @return Euclidean distance between the two points
+ */
+ public static double calculate(final double x1, final double y1, final double x2, final double y2) {
+ final double deltaX = x2 - x1;
+ final double deltaY = y2 - y1;
+ return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/maths/PerfectSquare.java b/src/main/java/com/thealgorithms/maths/PerfectSquare.java
index e9318bd7d805..aec43062121a 100644
--- a/src/main/java/com/thealgorithms/maths/PerfectSquare.java
+++ b/src/main/java/com/thealgorithms/maths/PerfectSquare.java
@@ -15,6 +15,9 @@ private PerfectSquare() {
* false
*/
public static boolean isPerfectSquare(final int number) {
+ if (number < 0) {
+ return false;
+ }
final int sqrt = (int) Math.sqrt(number);
return sqrt * sqrt == number;
}
@@ -27,6 +30,9 @@ public static boolean isPerfectSquare(final int number) {
* {@code false}
*/
public static boolean isPerfectSquareUsingPow(long number) {
+ if (number < 0) {
+ return false;
+ }
long a = (long) Math.pow(number, 1.0 / 2);
return a * a == number;
}
diff --git a/src/main/java/com/thealgorithms/others/cn/HammingDistance.java b/src/main/java/com/thealgorithms/others/cn/HammingDistance.java
deleted file mode 100644
index c8239d53d606..000000000000
--- a/src/main/java/com/thealgorithms/others/cn/HammingDistance.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.thealgorithms.others.cn;
-
-public final class HammingDistance {
- private HammingDistance() {
- }
-
- private static void checkChar(char inChar) {
- if (inChar != '0' && inChar != '1') {
- throw new IllegalArgumentException("Input must be a binary string.");
- }
- }
-
- public static int compute(char charA, char charB) {
- checkChar(charA);
- checkChar(charB);
- return charA == charB ? 0 : 1;
- }
-
- public static int compute(String bitsStrA, String bitsStrB) {
- if (bitsStrA.length() != bitsStrB.length()) {
- throw new IllegalArgumentException("Input strings must have the same length.");
- }
-
- int totalErrorBitCount = 0;
-
- for (int i = 0; i < bitsStrA.length(); i++) {
- totalErrorBitCount += compute(bitsStrA.charAt(i), bitsStrB.charAt(i));
- }
-
- return totalErrorBitCount;
- }
-}
diff --git a/src/main/java/com/thealgorithms/prefixsum/DifferenceArray.java b/src/main/java/com/thealgorithms/prefixsum/DifferenceArray.java
new file mode 100644
index 000000000000..1be55039cff0
--- /dev/null
+++ b/src/main/java/com/thealgorithms/prefixsum/DifferenceArray.java
@@ -0,0 +1,87 @@
+package com.thealgorithms.prefixsum;
+
+/**
+ * Implements the Difference Array algorithm.
+ *
+ *
+ * The Difference Array is an auxiliary data structure that enables efficient range update operations.
+ * It is based on the mathematical concept of Finite Differences.
+ *
+ *
+ *
+ * This method uses a branchless approach by allocating an extra element at the end
+ * of the array, avoiding the conditional check for the right boundary.
+ *
+ *
+ * @param l The starting index (inclusive).
+ * @param r The ending index (inclusive).
+ * @param val The value to add.
+ * @throws IllegalArgumentException if the range is invalid.
+ */
+ public void update(int l, int r, int val) {
+ if (l < 0 || r >= n || l > r) {
+ throw new IllegalArgumentException(String.format("Invalid range: [%d, %d] for array of size %d", l, r, n));
+ }
+
+ differenceArray[l] += val;
+ differenceArray[r + 1] -= val;
+ }
+
+ /**
+ * Reconstructs the final array using prefix sums.
+ *
+ * @return The resulting array after all updates. Returns long[] to handle potential overflows.
+ */
+ public long[] getResultArray() {
+ long[] result = new long[n];
+ result[0] = differenceArray[0];
+
+ for (int i = 1; i < n; i++) {
+ result[i] = differenceArray[i] + result[i - 1];
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/prefixsum/PrefixSum.java b/src/main/java/com/thealgorithms/prefixsum/PrefixSum.java
new file mode 100644
index 000000000000..47f6366e2924
--- /dev/null
+++ b/src/main/java/com/thealgorithms/prefixsum/PrefixSum.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.prefixsum;
+
+/**
+ * A class that implements the Prefix Sum algorithm.
+ *
+ * Prefix Sum is a technique used to preprocess an array such that
+ * range sum queries can be answered in O(1) time.
+ * The preprocessing step takes O(N) time.
+ *
+ *
This implementation uses a long array for the prefix sums to prevent
+ * integer overflow when the sum of elements exceeds Integer.MAX_VALUE.
+ *
+ * @see Prefix Sum (Wikipedia)
+ * @author Chahat Sandhu, singhc7
+ */
+public class PrefixSum {
+
+ private final long[] prefixSums;
+
+ /**
+ * Constructor to preprocess the input array.
+ *
+ * @param array The input integer array.
+ * @throws IllegalArgumentException if the array is null.
+ */
+ public PrefixSum(int[] array) {
+ if (array == null) {
+ throw new IllegalArgumentException("Input array cannot be null");
+ }
+ this.prefixSums = new long[array.length + 1];
+ this.prefixSums[0] = 0;
+
+ for (int i = 0; i < array.length; i++) {
+ // Automatically promotes int to long during addition
+ this.prefixSums[i + 1] = this.prefixSums[i] + array[i];
+ }
+ }
+
+ /**
+ * Calculates the sum of elements in the range [left, right].
+ * Indices are 0-based.
+ *
+ * @param left The starting index (inclusive).
+ * @param right The ending index (inclusive).
+ * @return The sum of elements from index left to right as a long.
+ * @throws IndexOutOfBoundsException if indices are out of valid range.
+ */
+ public long sumRange(int left, int right) {
+ if (left < 0 || right >= prefixSums.length - 1 || left > right) {
+ throw new IndexOutOfBoundsException("Invalid range indices");
+ }
+ return prefixSums[right + 1] - prefixSums[left];
+ }
+}
diff --git a/src/main/java/com/thealgorithms/prefixsum/PrefixSum2D.java b/src/main/java/com/thealgorithms/prefixsum/PrefixSum2D.java
new file mode 100644
index 000000000000..9c168bc6bcc4
--- /dev/null
+++ b/src/main/java/com/thealgorithms/prefixsum/PrefixSum2D.java
@@ -0,0 +1,64 @@
+package com.thealgorithms.prefixsum;
+
+/**
+ * A class that implements the 2D Prefix Sum algorithm.
+ *
+ *
2D Prefix Sum is a technique used to preprocess a 2D matrix such that
+ * sub-matrix sum queries can be answered in O(1) time.
+ * The preprocessing step takes O(N*M) time.
+ *
+ *
This implementation uses a long array for the prefix sums to prevent
+ * integer overflow.
+ *
+ * @see Summed-area table (Wikipedia)
+ * @author Chahat Sandhu, singhc7
+ */
+public class PrefixSum2D {
+
+ private final long[][] prefixSums;
+
+ /**
+ * Constructor to preprocess the input matrix.
+ *
+ * @param matrix The input integer matrix.
+ * @throws IllegalArgumentException if the matrix is null or empty.
+ */
+ public PrefixSum2D(int[][] matrix) {
+ if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
+ throw new IllegalArgumentException("Input matrix cannot be null or empty");
+ }
+
+ int rows = matrix.length;
+ int cols = matrix[0].length;
+ this.prefixSums = new long[rows + 1][cols + 1];
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < cols; j++) {
+ // P[i+1][j+1] = current + above + left - diagonal_overlap
+ this.prefixSums[i + 1][j + 1] = matrix[i][j] + this.prefixSums[i][j + 1] + this.prefixSums[i + 1][j] - this.prefixSums[i][j];
+ }
+ }
+ }
+
+ /**
+ * Calculates the sum of the sub-matrix defined by (row1, col1) to (row2, col2).
+ * Indices are 0-based.
+ *
+ * @param row1 Top row index.
+ * @param col1 Left column index.
+ * @param row2 Bottom row index.
+ * @param col2 Right column index.
+ * @return The sum of the sub-matrix.
+ * @throws IndexOutOfBoundsException if indices are invalid.
+ */
+ public long sumRegion(int row1, int col1, int row2, int col2) {
+ if (row1 < 0 || row2 >= prefixSums.length - 1 || row2 < row1) {
+ throw new IndexOutOfBoundsException("Invalid row indices");
+ }
+ if (col1 < 0 || col2 >= prefixSums[0].length - 1 || col2 < col1) {
+ throw new IndexOutOfBoundsException("Invalid column indices");
+ }
+
+ return prefixSums[row2 + 1][col2 + 1] - prefixSums[row1][col2 + 1] - prefixSums[row2 + 1][col1] + prefixSums[row1][col1];
+ }
+}
diff --git a/src/main/java/com/thealgorithms/prefixsum/SubarraySumEqualsK.java b/src/main/java/com/thealgorithms/prefixsum/SubarraySumEqualsK.java
new file mode 100644
index 000000000000..d6a6bbc01663
--- /dev/null
+++ b/src/main/java/com/thealgorithms/prefixsum/SubarraySumEqualsK.java
@@ -0,0 +1,72 @@
+package com.thealgorithms.prefixsum;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Implements an algorithm to count the number of continuous subarrays
+ * whose sum equals a given value k.
+ *
+ *
+ * This algorithm uses the Prefix Sum technique combined with a HashMap
+ * to achieve O(N) time complexity.
+ *
+ *
+ *
+ * Let prefixSum[i] be the sum of elements from index 0 to i.
+ * A subarray (j + 1) to i has sum k if:
+ *
+ *
+ * The HashMap stores the frequency of each prefix sum encountered so far.
+ *
+ *
+ * prefixSumFrequency = new HashMap<>();
+ prefixSumFrequency.put(0L, 1);
+
+ long prefixSum = 0;
+ int count = 0;
+
+ for (int num : nums) {
+ prefixSum += num;
+
+ long requiredSum = prefixSum - k;
+ count += prefixSumFrequency.getOrDefault(requiredSum, 0);
+
+ prefixSumFrequency.put(prefixSum, prefixSumFrequency.getOrDefault(prefixSum, 0) + 1);
+ }
+
+ return count;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/recursion/FibonacciSeries.java b/src/main/java/com/thealgorithms/recursion/FibonacciSeries.java
index 9bc6da2f7443..9c809858099e 100644
--- a/src/main/java/com/thealgorithms/recursion/FibonacciSeries.java
+++ b/src/main/java/com/thealgorithms/recursion/FibonacciSeries.java
@@ -1,16 +1,26 @@
package com.thealgorithms.recursion;
-/*
- The Fibonacci series is a sequence of numbers where each number is the sum of the two preceding ones,
- starting with 0 and 1.
- NUMBER 0 1 2 3 4 5 6 7 8 9 10 ...
- FIBONACCI 0 1 1 2 3 5 8 13 21 34 55 ...
-*/
+/**
+ * The Fibonacci series is a sequence of numbers where each number is the sum of the two preceding ones,
+ * starting with 0 and 1.
+ *
+ * Example:
+ * 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ...
+ *
+ */
public final class FibonacciSeries {
private FibonacciSeries() {
throw new UnsupportedOperationException("Utility class");
}
+
+ /**
+ * Calculates the nth term in the Fibonacci sequence using recursion.
+ *
+ * @param n the position in the Fibonacci sequence (must be non-negative)
+ * @return the nth Fibonacci number
+ * @throws IllegalArgumentException if n is negative
+ */
public static int fibonacci(int n) {
if (n < 0) {
throw new IllegalArgumentException("n must be a non-negative integer");
diff --git a/src/main/java/com/thealgorithms/searches/BinarySearch.java b/src/main/java/com/thealgorithms/searches/BinarySearch.java
index bedad1667f33..7a5361b280ea 100644
--- a/src/main/java/com/thealgorithms/searches/BinarySearch.java
+++ b/src/main/java/com/thealgorithms/searches/BinarySearch.java
@@ -3,12 +3,32 @@
import com.thealgorithms.devutils.searches.SearchAlgorithm;
/**
- * Binary search is one of the most popular algorithms The algorithm finds the
- * position of a target value within a sorted array
+ * Binary Search Algorithm Implementation
*
- *
- * Worst-case performance O(log n) Best-case performance O(1) Average
- * performance O(log n) Worst-case space complexity O(1)
+ *
Binary search is one of the most efficient searching algorithms for finding a target element
+ * in a SORTED array. It works by repeatedly dividing the search space in half, eliminating half of
+ * the remaining elements in each step.
+ *
+ *
IMPORTANT: This algorithm ONLY works correctly if the input array is sorted in ascending
+ * order.
+ *
+ *
Algorithm Overview: 1. Start with the entire array (left = 0, right = array.length - 1) 2.
+ * Calculate the middle index 3. Compare the middle element with the target: - If middle element
+ * equals target: Found! Return the index - If middle element is less than target: Search the right
+ * half - If middle element is greater than target: Search the left half 4. Repeat until element is
+ * found or search space is exhausted
+ *
+ *
Performance Analysis: - Best-case time complexity: O(1) - Element found at middle on first
+ * try - Average-case time complexity: O(log n) - Most common scenario - Worst-case time
+ * complexity: O(log n) - Element not found or at extreme end - Space complexity: O(1) - Only uses
+ * a constant amount of extra space
+ *
+ *
Example Walkthrough: Array: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] Target: 7
+ *
+ *
Step 1: left=0, right=9, mid=4, array[4]=9 (9 > 7, search left half) Step 2: left=0,
+ * right=3, mid=1, array[1]=3 (3 < 7, search right half) Step 3: left=2, right=3, mid=2,
+ * array[2]=5 (5 < 7, search right half) Step 4: left=3, right=3, mid=3, array[3]=7 (Found!
+ * Return index 3)
*
* @author Varun Upadhyay (https://github.com/varunu28)
* @author Podshivalov Nikita (https://github.com/nikitap492)
@@ -18,38 +38,89 @@
class BinarySearch implements SearchAlgorithm {
/**
- * @param array is an array where the element should be found
- * @param key is an element which should be found
- * @param is any comparable type
- * @return index of the element
+ * Generic method to perform binary search on any comparable type. This is the main entry point
+ * for binary search operations.
+ *
+ * Example Usage:
+ *
+ * Integer[] numbers = {1, 3, 5, 7, 9, 11};
+ * int result = new BinarySearch().find(numbers, 7);
+ * // result will be 3 (index of element 7)
+ *
+ * int notFound = new BinarySearch().find(numbers, 4);
+ * // notFound will be -1 (element 4 does not exist)
+ *
+ *
+ * @param The type of elements in the array (must be Comparable)
+ * @param array The sorted array to search in (MUST be sorted in ascending order)
+ * @param key The element to search for
+ * @return The index of the key if found, -1 if not found or if array is null/empty
*/
@Override
public > int find(T[] array, T key) {
+ // Handle edge case: empty array
+ if (array == null || array.length == 0) {
+ return -1;
+ }
+
+ // Delegate to the core search implementation
return search(array, key, 0, array.length - 1);
}
/**
- * This method implements the Generic Binary Search
+ * Core recursive implementation of binary search algorithm. This method divides the problem
+ * into smaller subproblems recursively.
+ *
+ * How it works:
+ *
+ * - Calculate the middle index to avoid integer overflow
+ * - Check if middle element matches the target
+ * - If not, recursively search either left or right half
+ * - Base case: left > right means element not found
+ *
+ *
+ * Time Complexity: O(log n) because we halve the search space each time.
+ * Space Complexity: O(log n) due to recursive call stack.
*
- * @param array The array to make the binary search
- * @param key The number you are looking for
- * @param left The lower bound
- * @param right The upper bound
- * @return the location of the key
+ * @param The type of elements (must be Comparable)
+ * @param array The sorted array to search in
+ * @param key The element we're looking for
+ * @param left The leftmost index of current search range (inclusive)
+ * @param right The rightmost index of current search range (inclusive)
+ * @return The index where key is located, or -1 if not found
*/
private > int search(T[] array, T key, int left, int right) {
+ // Base case: Search space is exhausted
+ // This happens when left pointer crosses right pointer
if (right < left) {
- return -1; // this means that the key not found
+ return -1; // Key not found in the array
}
- // find median
- int median = (left + right) >>> 1;
+
+ // Calculate middle index
+ // Using (left + right) / 2 could cause integer overflow for large arrays
+ // So we use: left + (right - left) / 2 which is mathematically equivalent
+ // but prevents overflow
+ int median = (left + right) >>> 1; // Unsigned right shift is faster division by 2
+
+ // Get the value at middle position for comparison
int comp = key.compareTo(array[median]);
+ // Case 1: Found the target element at middle position
if (comp == 0) {
- return median;
- } else if (comp < 0) {
+ return median; // Return the index where element was found
+ }
+ // Case 2: Target is smaller than middle element
+ // This means if target exists, it must be in the LEFT half
+ else if (comp < 0) {
+ // Recursively search the left half
+ // New search range: [left, median - 1]
return search(array, key, left, median - 1);
- } else {
+ }
+ // Case 3: Target is greater than middle element
+ // This means if target exists, it must be in the RIGHT half
+ else {
+ // Recursively search the right half
+ // New search range: [median + 1, right]
return search(array, key, median + 1, right);
}
}
diff --git a/src/main/java/com/thealgorithms/searches/LinearSearch.java b/src/main/java/com/thealgorithms/searches/LinearSearch.java
index c7b70edb5112..cb483d8dfedc 100644
--- a/src/main/java/com/thealgorithms/searches/LinearSearch.java
+++ b/src/main/java/com/thealgorithms/searches/LinearSearch.java
@@ -1,21 +1,26 @@
package com.thealgorithms.searches;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
-
/**
- * Linear search is the easiest search algorithm It works with sorted and
- * unsorted arrays (an binary search works only with sorted array) This
- * algorithm just compares all elements of an array to find a value
+ * Linear Search is a simple searching algorithm that checks
+ * each element of the array sequentially until the target
+ * value is found or the array ends.
+ *
+ * It works for both sorted and unsorted arrays.
*
- *
- * Worst-case performance O(n) Best-case performance O(1) Average performance
- * O(n) Worst-case space complexity
+ * Time Complexity:
+ * - Best case: O(1)
+ * - Average case: O(n)
+ * - Worst case: O(n)
*
- * @author Varun Upadhyay (https://github.com/varunu28)
- * @author Podshivalov Nikita (https://github.com/nikitap492)
+ * Space Complexity: O(1)
+ *
+ * @author Varun Upadhyay
+ * @author Podshivalov Nikita
* @see BinarySearch
* @see SearchAlgorithm
*/
+
public class LinearSearch implements SearchAlgorithm {
/**
diff --git a/src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java b/src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java
deleted file mode 100644
index 495e2e41bc5b..000000000000
--- a/src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.thealgorithms.searches;
-
-import com.thealgorithms.devutils.searches.SearchAlgorithm;
-
-/**
- * Binary search is one of the most popular algorithms The algorithm finds the
- * position of a target value within a sorted array
- *
- *
- * Worst-case performance O(log n) Best-case performance O(1) Average
- * performance O(log n) Worst-case space complexity O(1)
- *
- * @author D Sunil (https://github.com/sunilnitdgp)
- * @see SearchAlgorithm
- */
-
-public class PerfectBinarySearch implements SearchAlgorithm {
-
- /**
- * @param array is an array where the element should be found
- * @param key is an element which should be found
- * @param is any comparable type
- * @return index of the element
- */
- @Override
- public > int find(T[] array, T key) {
- return search(array, key, 0, array.length - 1);
- }
-
- /**
- * This method implements the Generic Binary Search iteratively.
- *
- * @param array The array to make the binary search
- * @param key The number you are looking for
- * @return the location of the key, or -1 if not found
- */
- private static > int search(T[] array, T key, int left, int right) {
- while (left <= right) {
- int median = (left + right) >>> 1;
- int comp = key.compareTo(array[median]);
-
- if (comp == 0) {
- return median; // Key found
- }
-
- if (comp < 0) {
- right = median - 1; // Adjust the right bound
- } else {
- left = median + 1; // Adjust the left bound
- }
- }
- return -1; // Key not found
- }
-}
diff --git a/src/main/java/com/thealgorithms/searches/RotatedBinarySearch.java b/src/main/java/com/thealgorithms/searches/RotatedBinarySearch.java
new file mode 100644
index 000000000000..86099b2fa2fa
--- /dev/null
+++ b/src/main/java/com/thealgorithms/searches/RotatedBinarySearch.java
@@ -0,0 +1,60 @@
+package com.thealgorithms.searches;
+
+import com.thealgorithms.devutils.searches.SearchAlgorithm;
+
+/**
+ * Searches for a key in a sorted array that has been rotated at an unknown pivot.
+ *
+ *
+ * Example:
+ * {@code [8, 9, 10, 1, 2, 3, 4, 5, 6, 7]}
+ *
+ *
+ * This is a modified binary search. When the array contains no duplicates, the
+ * time complexity is {@code O(log n)}. With duplicates, the algorithm still
+ * works but may degrade to {@code O(n)} in the worst case.
+ *
+ * @see Search in rotated sorted array
+ * @see SearchAlgorithm
+ */
+public final class RotatedBinarySearch implements SearchAlgorithm {
+
+ @Override
+ public > int find(T[] array, T key) {
+ int left = 0;
+ int right = array.length - 1;
+
+ while (left <= right) {
+ int middle = (left + right) >>> 1;
+ int cmp = key.compareTo(array[middle]);
+ if (cmp == 0) {
+ return middle;
+ }
+
+ // Handle duplicates: if we cannot determine which side is sorted.
+ if (array[left].compareTo(array[middle]) == 0 && array[middle].compareTo(array[right]) == 0) {
+ left++;
+ right--;
+ continue;
+ }
+
+ // Left half is sorted.
+ if (array[left].compareTo(array[middle]) <= 0) {
+ if (array[left].compareTo(key) <= 0 && key.compareTo(array[middle]) < 0) {
+ right = middle - 1;
+ } else {
+ left = middle + 1;
+ }
+ } else {
+ // Right half is sorted.
+ if (array[middle].compareTo(key) < 0 && key.compareTo(array[right]) <= 0) {
+ left = middle + 1;
+ } else {
+ right = middle - 1;
+ }
+ }
+ }
+
+ return -1;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearch.java b/src/main/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearch.java
deleted file mode 100644
index 6a2a46c2821f..000000000000
--- a/src/main/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearch.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.thealgorithms.searches;
-public final class SortOrderAgnosticBinarySearch {
- private SortOrderAgnosticBinarySearch() {
- }
- public static int find(int[] arr, int key) {
- int start = 0;
- int end = arr.length - 1;
- boolean arrDescending = arr[start] > arr[end]; // checking for Array is in ascending order or descending order.
- while (start <= end) {
- int mid = end - start / 2;
- if (arr[mid] == key) {
- return mid;
- }
- if (arrDescending) { // boolean is true then our array is in descending order
- if (key < arr[mid]) {
- start = mid + 1;
- } else {
- end = mid - 1;
- }
- } else { // otherwise our array is in ascending order
- if (key > arr[mid]) {
- start = mid + 1;
- } else {
- end = mid - 1;
- }
- }
- }
- return -1;
- }
-}
diff --git a/src/main/java/com/thealgorithms/slidingwindow/CountNiceSubarrays.java b/src/main/java/com/thealgorithms/slidingwindow/CountNiceSubarrays.java
new file mode 100644
index 000000000000..46f8deeb58dd
--- /dev/null
+++ b/src/main/java/com/thealgorithms/slidingwindow/CountNiceSubarrays.java
@@ -0,0 +1,99 @@
+package com.thealgorithms.slidingwindow;
+
+/**
+ * Counts the number of "nice subarrays".
+ * A nice subarray is a contiguous subarray that contains exactly k odd numbers.
+ *
+ * This implementation uses the sliding window technique.
+ *
+ * Reference:
+ * https://leetcode.com/problems/count-number-of-nice-subarrays/
+ *
+ * Time Complexity: O(n)
+ * Space Complexity: O(n)
+ */
+public final class CountNiceSubarrays {
+
+ // Private constructor to prevent instantiation
+ private CountNiceSubarrays() {
+ }
+
+ /**
+ * Returns the count of subarrays containing exactly k odd numbers.
+ *
+ * @param nums input array of integers
+ * @param k number of odd elements required in the subarray
+ * @return number of nice subarrays
+ */
+ public static int countNiceSubarrays(int[] nums, int k) {
+
+ int n = nums.length;
+
+ // Left pointer of the sliding window
+ int left = 0;
+
+ // Tracks number of odd elements in the current window
+ int oddCount = 0;
+
+ // Final answer: total number of nice subarrays
+ int result = 0;
+
+ /*
+ * memo[i] stores how many valid starting positions exist
+ * when the left pointer is at index i.
+ *
+ * This avoids recomputing the same values again.
+ */
+ int[] memo = new int[n];
+
+ // Right pointer moves forward to expand the window
+ for (int right = 0; right < n; right++) {
+
+ // If current element is odd, increment odd count
+ if ((nums[right] & 1) == 1) {
+ oddCount++;
+ }
+
+ /*
+ * If oddCount exceeds k, shrink the window from the left
+ * until oddCount becomes valid again.
+ */
+ if (oddCount > k) {
+ left += memo[left];
+ oddCount--;
+ }
+
+ /*
+ * When the window contains exactly k odd numbers,
+ * count all possible valid subarrays starting at `left`.
+ */
+ if (oddCount == k) {
+
+ /*
+ * If this left index hasn't been processed before,
+ * count how many consecutive even numbers follow it.
+ */
+ if (memo[left] == 0) {
+ int count = 0;
+ int temp = left;
+
+ // Count consecutive even numbers
+ while ((nums[temp] & 1) == 0) {
+ count++;
+ temp++;
+ }
+
+ /*
+ * Number of valid subarrays starting at `left`
+ * is (count of even numbers + 1)
+ */
+ memo[left] = count + 1;
+ }
+
+ // Add number of valid subarrays for this left position
+ result += memo[left];
+ }
+ }
+ return result;
+ }
+}
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..c45d6f1f02b2
--- /dev/null
+++ b/src/main/java/com/thealgorithms/sorts/SmoothSort.java
@@ -0,0 +1,168 @@
+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:
+ *
+ * - Best case: O(n) for already sorted input
+ * - Average case: O(n log n)
+ * - Worst case: O(n log n)
+ *
+ *
+ * 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 element type
+ * @return the sorted array
+ */
+ @Override
+ public > T[] sort(final T[] array) {
+ if (array.length < 2) {
+ return array;
+ }
+
+ final int last = array.length - 1;
+
+ // The forest shape is encoded as (p, pshift): p is a bit-vector of present tree orders,
+ // shifted right by pshift. pshift is the order of the rightmost (current) Leonardo tree.
+ long p = 1L;
+ int pshift = 1;
+
+ int head = 0;
+ while (head < last) {
+ if ((p & 3L) == 3L) {
+ sift(array, pshift, head);
+ p >>>= 2;
+ pshift += 2;
+ } else {
+ // Add a new singleton tree; if it will not be merged anymore, we must fully trinkle.
+ if (LEONARDO[pshift - 1] >= last - head) {
+ trinkle(array, p, pshift, head, false);
+ } else {
+ // This tree will be merged later, so it is enough to restore its internal heap property.
+ sift(array, pshift, head);
+ }
+
+ if (pshift == 1) {
+ // If L(1) is used, the new singleton is L(0).
+ p <<= 1;
+ pshift = 0;
+ } else {
+ // Otherwise, shift to order 1 and append a singleton of order 1.
+ p <<= (pshift - 1);
+ pshift = 1;
+ }
+ }
+
+ p |= 1L;
+ head++;
+ }
+
+ trinkle(array, p, pshift, head, false);
+
+ // Repeatedly remove the maximum (always at head) by shrinking the heap region.
+ while (pshift != 1 || p != 1L) {
+ if (pshift <= 1) {
+ // Rightmost tree is a singleton (order 0 or 1). Move to the previous tree root.
+ final long mask = p & ~1L;
+ final int shift = Long.numberOfTrailingZeros(mask);
+ p >>>= shift;
+ pshift += shift;
+ } else {
+ // Split a tree of order (pshift) into two children trees of orders (pshift-1) and (pshift-2).
+ p <<= 2;
+ p ^= 7L;
+ pshift -= 2;
+
+ trinkle(array, p >>> 1, pshift + 1, head - LEONARDO[pshift] - 1, true);
+ trinkle(array, p, pshift, head - 1, true);
+ }
+
+ head--;
+ }
+
+ return array;
+ }
+
+ private static > void sift(final T[] array, int order, int root) {
+ final T value = array[root];
+
+ while (order > 1) {
+ final int right = root - 1;
+ final int left = root - 1 - LEONARDO[order - 2];
+
+ if (!SortUtils.less(value, array[left]) && !SortUtils.less(value, array[right])) {
+ break;
+ }
+
+ if (!SortUtils.less(array[left], array[right])) {
+ array[root] = array[left];
+ root = left;
+ order -= 1;
+ } else {
+ array[root] = array[right];
+ root = right;
+ order -= 2;
+ }
+ }
+
+ array[root] = value;
+ }
+
+ private static > void trinkle(final T[] array, long p, int order, int root, boolean trusty) {
+ final T value = array[root];
+
+ while (p != 1L) {
+ final int stepson = root - LEONARDO[order];
+
+ if (!SortUtils.less(value, array[stepson])) {
+ break;
+ }
+
+ if (!trusty && order > 1) {
+ final int right = root - 1;
+ final int left = root - 1 - LEONARDO[order - 2];
+
+ if (!SortUtils.less(array[right], array[stepson]) || !SortUtils.less(array[left], array[stepson])) {
+ break;
+ }
+ }
+
+ array[root] = array[stepson];
+ root = stepson;
+
+ final long mask = p & ~1L;
+ final int shift = Long.numberOfTrailingZeros(mask);
+ p >>>= shift;
+ order += shift;
+ trusty = false;
+ }
+
+ if (!trusty) {
+ array[root] = value;
+ sift(array, order, root);
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/sorts/TournamentSort.java b/src/main/java/com/thealgorithms/sorts/TournamentSort.java
new file mode 100644
index 000000000000..ec51a1e2c0a9
--- /dev/null
+++ b/src/main/java/com/thealgorithms/sorts/TournamentSort.java
@@ -0,0 +1,84 @@
+package com.thealgorithms.sorts;
+
+import java.util.Arrays;
+
+/**
+ * Tournament Sort algorithm implementation.
+ *
+ * Tournament sort builds a winner tree (a complete binary tree storing the index
+ * of the smallest element in each subtree). It then repeatedly extracts the
+ * winner (minimum) and updates the path from the removed leaf to the root.
+ *
+ * Time Complexity:
+ * - Best case: O(n log n)
+ * - Average case: O(n log n)
+ * - Worst case: O(n log n)
+ *
+ * Space Complexity: O(n) β additional winner-tree storage
+ *
+ * @see Tournament Sort Algorithm
+ * @see SortAlgorithm
+ */
+public class TournamentSort implements SortAlgorithm {
+
+ @Override
+ public > T[] sort(T[] array) {
+ if (array == null || array.length < 2) {
+ return array;
+ }
+
+ final int n = array.length;
+ final int leafCount = nextPowerOfTwo(n);
+
+ // Winner tree represented as an array:
+ // - Leaves live at [leafCount .. 2*leafCount)
+ // - Internal nodes live at [1 .. leafCount)
+ // Each node stores an index into the original array or -1 for "empty".
+ final int[] tree = new int[2 * leafCount];
+ Arrays.fill(tree, -1);
+
+ for (int i = 0; i < n; i++) {
+ tree[leafCount + i] = i;
+ }
+
+ for (int node = leafCount - 1; node >= 1; node--) {
+ tree[node] = winnerIndex(array, tree[node * 2], tree[node * 2 + 1]);
+ }
+
+ final T[] result = array.clone();
+ for (int out = 0; out < n; out++) {
+ final int winner = tree[1];
+ result[out] = array[winner];
+
+ int node = leafCount + winner;
+ tree[node] = -1;
+
+ for (node /= 2; node >= 1; node /= 2) {
+ tree[node] = winnerIndex(array, tree[node * 2], tree[node * 2 + 1]);
+ }
+ }
+
+ System.arraycopy(result, 0, array, 0, n);
+ return array;
+ }
+
+ private static int nextPowerOfTwo(int n) {
+ int power = 1;
+ while (power < n) {
+ power <<= 1;
+ }
+ return power;
+ }
+
+ private static > int winnerIndex(T[] array, int leftIndex, int rightIndex) {
+ if (leftIndex == -1) {
+ return rightIndex;
+ }
+ if (rightIndex == -1) {
+ return leftIndex;
+ }
+
+ // If equal, prefer the left element to keep ordering deterministic.
+ return SortUtils.less(array[rightIndex], array[leftIndex]) ? rightIndex : leftIndex;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/strings/KMP.java b/src/main/java/com/thealgorithms/strings/KMP.java
index 07d3b0415006..0317abe6f39a 100644
--- a/src/main/java/com/thealgorithms/strings/KMP.java
+++ b/src/main/java/com/thealgorithms/strings/KMP.java
@@ -1,5 +1,8 @@
package com.thealgorithms.strings;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Implementation of KnuthβMorrisβPratt algorithm Usage: see the main function
* for an example
@@ -8,16 +11,19 @@ public final class KMP {
private KMP() {
}
- // a working example
-
- public static void main(String[] args) {
- final String haystack = "AAAAABAAABA"; // This is the full string
- final String needle = "AAAA"; // This is the substring that we want to find
- kmpMatcher(haystack, needle);
- }
+ /**
+ * find the starting index in string haystack[] that matches the search word P[]
+ *
+ * @param haystack The text to be searched
+ * @param needle The pattern to be searched for
+ * @return A list of starting indices where the pattern is found
+ */
+ public static List kmpMatcher(final String haystack, final String needle) {
+ List occurrences = new ArrayList<>();
+ if (haystack == null || needle == null || needle.isEmpty()) {
+ return occurrences;
+ }
- // find the starting index in string haystack[] that matches the search word P[]
- public static void kmpMatcher(final String haystack, final String needle) {
final int m = haystack.length();
final int n = needle.length();
final int[] pi = computePrefixFunction(needle);
@@ -32,10 +38,11 @@ public static void kmpMatcher(final String haystack, final String needle) {
}
if (q == n) {
- System.out.println("Pattern starts: " + (i + 1 - n));
+ occurrences.add(i + 1 - n);
q = pi[q - 1];
}
}
+ return occurrences;
}
// return the prefix function
diff --git a/src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java b/src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java
deleted file mode 100644
index ca500357ba77..000000000000
--- a/src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.thealgorithms.strings;
-
-final class LongestPalindromicSubstring {
- private LongestPalindromicSubstring() {
- }
-
- /**
- * Finds the longest palindromic substring in the given string.
- *
- * @param s the input string
- * @return the longest palindromic substring
- */
- public static String longestPalindrome(String s) {
- if (s == null || s.isEmpty()) {
- return "";
- }
- String maxStr = "";
- for (int i = 0; i < s.length(); ++i) {
- for (int j = i; j < s.length(); ++j) {
- if (isValid(s, i, j) && (j - i + 1 > maxStr.length())) {
- maxStr = s.substring(i, j + 1);
- }
- }
- }
- return maxStr;
- }
-
- private static boolean isValid(String s, int lo, int hi) {
- int n = hi - lo + 1;
- for (int i = 0; i < n / 2; ++i) {
- if (s.charAt(lo + i) != s.charAt(hi - i)) {
- return false;
- }
- }
- return true;
- }
-}
diff --git a/src/main/java/com/thealgorithms/strings/MyAtoi.java b/src/main/java/com/thealgorithms/strings/MyAtoi.java
index 5a7c2ce53b1c..92de4039a582 100644
--- a/src/main/java/com/thealgorithms/strings/MyAtoi.java
+++ b/src/main/java/com/thealgorithms/strings/MyAtoi.java
@@ -45,7 +45,9 @@ public static int myAtoi(String s) {
int number = 0;
while (index < length) {
char ch = s.charAt(index);
- if (!Character.isDigit(ch)) {
+
+ // Accept only ASCII digits
+ if (ch < '0' || ch > '9') {
break;
}
diff --git a/src/main/java/com/thealgorithms/strings/RabinKarp.java b/src/main/java/com/thealgorithms/strings/RabinKarp.java
index bb8df3358453..be17f87c3656 100644
--- a/src/main/java/com/thealgorithms/strings/RabinKarp.java
+++ b/src/main/java/com/thealgorithms/strings/RabinKarp.java
@@ -1,32 +1,30 @@
package com.thealgorithms.strings;
-import java.util.Scanner;
+import java.util.ArrayList;
+import java.util.List;
/**
* @author Prateek Kumar Oraon (https://github.com/prateekKrOraon)
*
- An implementation of Rabin-Karp string matching algorithm
- Program will simply end if there is no match
+ * An implementation of Rabin-Karp string matching algorithm
+ * Program will simply end if there is no match
*/
public final class RabinKarp {
private RabinKarp() {
}
- public static Scanner scanner = null;
- public static final int ALPHABET_SIZE = 256;
+ private static final int ALPHABET_SIZE = 256;
- public static void main(String[] args) {
- scanner = new Scanner(System.in);
- System.out.println("Enter String");
- String text = scanner.nextLine();
- System.out.println("Enter pattern");
- String pattern = scanner.nextLine();
-
- int q = 101;
- searchPat(text, pattern, q);
+ public static List search(String text, String pattern) {
+ return search(text, pattern, 101);
}
- private static void searchPat(String text, String pattern, int q) {
+ public static List search(String text, String pattern, int q) {
+ List occurrences = new ArrayList<>();
+ if (text == null || pattern == null || pattern.isEmpty()) {
+ return occurrences;
+ }
+
int m = pattern.length();
int n = text.length();
int t = 0;
@@ -35,48 +33,42 @@ private static void searchPat(String text, String pattern, int q) {
int j = 0;
int i = 0;
- h = (int) Math.pow(ALPHABET_SIZE, m - 1) % q;
+ if (m > n) {
+ return new ArrayList<>();
+ }
+
+ // h = pow(ALPHABET_SIZE, m-1) % q
+ for (i = 0; i < m - 1; i++) {
+ h = h * ALPHABET_SIZE % q;
+ }
for (i = 0; i < m; i++) {
- // hash value is calculated for each character and then added with the hash value of the
- // next character for pattern as well as the text for length equal to the length of
- // pattern
p = (ALPHABET_SIZE * p + pattern.charAt(i)) % q;
t = (ALPHABET_SIZE * t + text.charAt(i)) % q;
}
for (i = 0; i <= n - m; i++) {
- // if the calculated hash value of the pattern and text matches then
- // all the characters of the pattern is matched with the text of length equal to length
- // of the pattern if all matches then pattern exist in string if not then the hash value
- // of the first character of the text is subtracted and hash value of the next character
- // after the end of the evaluated characters is added
if (p == t) {
- // if hash value matches then the individual characters are matched
for (j = 0; j < m; j++) {
- // if not matched then break out of the loop
if (text.charAt(i + j) != pattern.charAt(j)) {
break;
}
}
- // if all characters are matched then pattern exist in the string
if (j == m) {
- System.out.println("Pattern found at index " + i);
+ occurrences.add(i);
}
}
- // if i
- * A string is considered valid if:
- *
- * - Open brackets are closed by the same type of brackets.
- * - Brackets are closed in the correct order.
- * - Every closing bracket has a corresponding open bracket of the same type.
- *
- *
- * Allowed characters: '(', ')', '{', '}', '[', ']'
- */
-public final class ValidParentheses {
- private ValidParentheses() {
- }
-
- private static final Map BRACKET_PAIRS = Map.of(')', '(', '}', '{', ']', '[');
-
- /**
- * Checks if the input string has valid parentheses.
- *
- * @param s the string containing only bracket characters
- * @return true if valid, false otherwise
- * @throws IllegalArgumentException if the string contains invalid characters or is null
- */
- public static boolean isValid(String s) {
- if (s == null) {
- throw new IllegalArgumentException("Input string cannot be null");
- }
-
- Deque stack = new ArrayDeque<>();
-
- for (char c : s.toCharArray()) {
- if (BRACKET_PAIRS.containsValue(c)) {
- stack.push(c); // opening bracket
- } else if (BRACKET_PAIRS.containsKey(c)) {
- if (stack.isEmpty() || stack.pop() != BRACKET_PAIRS.get(c)) {
- return false;
- }
- } else {
- throw new IllegalArgumentException("Unexpected character: " + c);
- }
- }
-
- return stack.isEmpty();
- }
-}
diff --git a/src/test/java/com/thealgorithms/backtracking/CombinationTest.java b/src/test/java/com/thealgorithms/backtracking/CombinationTest.java
index a9d1163f3ecd..5d2f99ccadf8 100644
--- a/src/test/java/com/thealgorithms/backtracking/CombinationTest.java
+++ b/src/test/java/com/thealgorithms/backtracking/CombinationTest.java
@@ -28,16 +28,16 @@ void testNoElement() {
@Test
void testLengthOne() {
List> result = Combination.combination(new Integer[] {1, 2}, 1);
- assertTrue(result.get(0).iterator().next() == 1);
- assertTrue(result.get(1).iterator().next() == 2);
+ assertEquals(1, result.get(0).iterator().next());
+ assertEquals(2, result.get(1).iterator().next());
}
@Test
void testLengthTwo() {
List> result = Combination.combination(new Integer[] {1, 2}, 2);
Integer[] arr = result.get(0).toArray(new Integer[2]);
- assertTrue(arr[0] == 1);
- assertTrue(arr[1] == 2);
+ assertEquals(1, arr[0]);
+ assertEquals(2, arr[1]);
}
@Test
diff --git a/src/test/java/com/thealgorithms/backtracking/PermutationTest.java b/src/test/java/com/thealgorithms/backtracking/PermutationTest.java
index 76a714829109..54747e5e73a1 100644
--- a/src/test/java/com/thealgorithms/backtracking/PermutationTest.java
+++ b/src/test/java/com/thealgorithms/backtracking/PermutationTest.java
@@ -12,13 +12,13 @@ public class PermutationTest {
@Test
void testNoElement() {
List result = Permutation.permutation(new Integer[] {});
- assertEquals(result.get(0).length, 0);
+ assertEquals(0, result.get(0).length);
}
@Test
void testSingleElement() {
List result = Permutation.permutation(new Integer[] {1});
- assertEquals(result.get(0)[0], 1);
+ assertEquals(1, result.get(0)[0]);
}
@Test
diff --git a/src/test/java/com/thealgorithms/ciphers/ECCTest.java b/src/test/java/com/thealgorithms/ciphers/ECCTest.java
index 701f801af1c8..b78ba51f7c3e 100644
--- a/src/test/java/com/thealgorithms/ciphers/ECCTest.java
+++ b/src/test/java/com/thealgorithms/ciphers/ECCTest.java
@@ -37,7 +37,7 @@ void testEncrypt() {
System.out.println("Base Point G: " + curve.getBasePoint());
// Verify that the ciphertext is not empty
- assertEquals(cipherText.length, 2); // Check if the ciphertext contains two points (R and S)
+ assertEquals(2, cipherText.length); // Check if the ciphertext contains two points (R and S)
// Output the encrypted coordinate points
System.out.println("Encrypted Points:");
diff --git a/src/test/java/com/thealgorithms/ciphers/ElGamalCipherTest.java b/src/test/java/com/thealgorithms/ciphers/ElGamalCipherTest.java
new file mode 100644
index 000000000000..63dec4846bbc
--- /dev/null
+++ b/src/test/java/com/thealgorithms/ciphers/ElGamalCipherTest.java
@@ -0,0 +1,145 @@
+package com.thealgorithms.ciphers;
+
+import java.math.BigInteger;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/**
+ * Unit tests for ElGamalCipher.
+ * Includes property-based testing (homomorphism), probabilistic checks,
+ * and boundary validation.
+ */
+class ElGamalCipherTest {
+
+ private static ElGamalCipher.KeyPair sharedKeys;
+
+ @BeforeAll
+ static void setup() {
+ // Generate 256-bit keys for efficient unit testing
+ sharedKeys = ElGamalCipher.generateKeys(256);
+ }
+
+ @Test
+ @DisplayName("Test Key Generation Validity")
+ void testKeyGeneration() {
+ Assertions.assertNotNull(sharedKeys.p());
+ Assertions.assertNotNull(sharedKeys.g());
+ Assertions.assertNotNull(sharedKeys.x());
+ Assertions.assertNotNull(sharedKeys.y());
+
+ // Verify generator bounds: 1 < g < p
+ Assertions.assertTrue(sharedKeys.g().compareTo(BigInteger.ONE) > 0);
+ Assertions.assertTrue(sharedKeys.g().compareTo(sharedKeys.p()) < 0);
+
+ // Verify private key bounds: 1 < x < p-1
+ Assertions.assertTrue(sharedKeys.x().compareTo(BigInteger.ONE) > 0);
+ Assertions.assertTrue(sharedKeys.x().compareTo(sharedKeys.p().subtract(BigInteger.ONE)) < 0);
+ }
+
+ @Test
+ @DisplayName("Security Check: Probabilistic Encryption")
+ void testSemanticSecurity() {
+ // Encrypting the same message twice MUST yield different ciphertexts
+ // due to the random ephemeral key 'k'.
+ BigInteger message = new BigInteger("123456789");
+
+ ElGamalCipher.CipherText c1 = ElGamalCipher.encrypt(message, sharedKeys.p(), sharedKeys.g(), sharedKeys.y());
+ ElGamalCipher.CipherText c2 = ElGamalCipher.encrypt(message, sharedKeys.p(), sharedKeys.g(), sharedKeys.y());
+
+ // Check that the ephemeral keys (and thus 'a' components) were different
+ Assertions.assertNotEquals(c1.a(), c2.a(), "Ciphertexts must be randomized (Semantic Security violation)");
+ Assertions.assertNotEquals(c1.b(), c2.b());
+
+ // But both must decrypt to the original message
+ Assertions.assertEquals(ElGamalCipher.decrypt(c1, sharedKeys.x(), sharedKeys.p()), message);
+ Assertions.assertEquals(ElGamalCipher.decrypt(c2, sharedKeys.x(), sharedKeys.p()), message);
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideMessages")
+ @DisplayName("Parameterized Test: Encrypt and Decrypt various messages")
+ void testEncryptDecrypt(String messageStr) {
+ BigInteger message = new BigInteger(messageStr.getBytes());
+
+ // Skip if message exceeds the test key size (256 bits)
+ if (message.compareTo(sharedKeys.p()) >= 0) {
+ return;
+ }
+
+ ElGamalCipher.CipherText ciphertext = ElGamalCipher.encrypt(message, sharedKeys.p(), sharedKeys.g(), sharedKeys.y());
+ BigInteger decrypted = ElGamalCipher.decrypt(ciphertext, sharedKeys.x(), sharedKeys.p());
+
+ Assertions.assertEquals(message, decrypted, "Decrypted BigInteger must match original");
+ Assertions.assertEquals(messageStr, new String(decrypted.toByteArray()), "Decrypted string must match original");
+ }
+
+ static Stream provideMessages() {
+ return Stream.of("Hello World", "TheAlgorithms", "A", "1234567890", "!@#$%^&*()");
+ }
+
+ @Test
+ @DisplayName("Edge Case: Message equals 0")
+ void testMessageZero() {
+ BigInteger zero = BigInteger.ZERO;
+ ElGamalCipher.CipherText ciphertext = ElGamalCipher.encrypt(zero, sharedKeys.p(), sharedKeys.g(), sharedKeys.y());
+ BigInteger decrypted = ElGamalCipher.decrypt(ciphertext, sharedKeys.x(), sharedKeys.p());
+
+ Assertions.assertEquals(zero, decrypted, "Should successfully encrypt/decrypt zero");
+ }
+
+ @Test
+ @DisplayName("Edge Case: Message equals p-1")
+ void testMessageMaxBound() {
+ BigInteger pMinus1 = sharedKeys.p().subtract(BigInteger.ONE);
+ ElGamalCipher.CipherText ciphertext = ElGamalCipher.encrypt(pMinus1, sharedKeys.p(), sharedKeys.g(), sharedKeys.y());
+ BigInteger decrypted = ElGamalCipher.decrypt(ciphertext, sharedKeys.x(), sharedKeys.p());
+
+ Assertions.assertEquals(pMinus1, decrypted, "Should successfully encrypt/decrypt p-1");
+ }
+
+ @Test
+ @DisplayName("Negative Test: Message >= p should fail")
+ void testMessageTooLarge() {
+ BigInteger tooLarge = sharedKeys.p();
+ Assertions.assertThrows(IllegalArgumentException.class, () -> ElGamalCipher.encrypt(tooLarge, sharedKeys.p(), sharedKeys.g(), sharedKeys.y()));
+ }
+
+ @Test
+ @DisplayName("Negative Test: Decrypt with wrong private key")
+ void testWrongKeyDecryption() {
+ BigInteger message = new BigInteger("99999");
+ ElGamalCipher.CipherText ciphertext = ElGamalCipher.encrypt(message, sharedKeys.p(), sharedKeys.g(), sharedKeys.y());
+
+ // Generate a fake private key
+ BigInteger wrongX = sharedKeys.x().add(BigInteger.ONE);
+
+ BigInteger decrypted = ElGamalCipher.decrypt(ciphertext, wrongX, sharedKeys.p());
+
+ Assertions.assertNotEquals(message, decrypted, "Decryption with wrong key must yield incorrect result");
+ }
+
+ @Test
+ @DisplayName("Property Test: Multiplicative Homomorphism")
+ void testHomomorphism() {
+ BigInteger m1 = new BigInteger("50");
+ BigInteger m2 = BigInteger.TEN; // Fix: Replaced new BigInteger("10") with BigInteger.TEN
+
+ ElGamalCipher.CipherText c1 = ElGamalCipher.encrypt(m1, sharedKeys.p(), sharedKeys.g(), sharedKeys.y());
+ ElGamalCipher.CipherText c2 = ElGamalCipher.encrypt(m2, sharedKeys.p(), sharedKeys.g(), sharedKeys.y());
+
+ // Multiply ciphertexts component-wise: (a1*a2, b1*b2)
+ BigInteger aNew = c1.a().multiply(c2.a()).mod(sharedKeys.p());
+ BigInteger bNew = c1.b().multiply(c2.b()).mod(sharedKeys.p());
+ ElGamalCipher.CipherText cCombined = new ElGamalCipher.CipherText(aNew, bNew);
+
+ BigInteger decrypted = ElGamalCipher.decrypt(cCombined, sharedKeys.x(), sharedKeys.p());
+ BigInteger expected = m1.multiply(m2).mod(sharedKeys.p());
+
+ Assertions.assertEquals(expected, decrypted, "Cipher must satisfy multiplicative homomorphism");
+ }
+}
diff --git a/src/test/java/com/thealgorithms/ciphers/PermutationCipherTest.java b/src/test/java/com/thealgorithms/ciphers/PermutationCipherTest.java
index 4ba6787cc97e..ecb7455c1ba2 100644
--- a/src/test/java/com/thealgorithms/ciphers/PermutationCipherTest.java
+++ b/src/test/java/com/thealgorithms/ciphers/PermutationCipherTest.java
@@ -1,6 +1,7 @@
package com.thealgorithms.ciphers;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
@@ -121,8 +122,8 @@ void testNullString() {
String decrypted = cipher.decrypt(encrypted, key);
// then
- assertEquals(null, encrypted);
- assertEquals(null, decrypted);
+ assertNull(encrypted);
+ assertNull(decrypted);
}
@Test
diff --git a/src/test/java/com/thealgorithms/compression/LZ78Test.java b/src/test/java/com/thealgorithms/compression/LZ78Test.java
index 7889b50b76f3..da1fd8d23318 100644
--- a/src/test/java/com/thealgorithms/compression/LZ78Test.java
+++ b/src/test/java/com/thealgorithms/compression/LZ78Test.java
@@ -1,7 +1,6 @@
package com.thealgorithms.compression;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
@@ -286,7 +285,6 @@ void testTokenStructure() {
// All tokens should have valid indices (>= 0)
for (LZ78.Token token : compressed) {
assertTrue(token.index() >= 0);
- assertNotNull(token.nextChar());
}
String decompressed = LZ78.decompress(compressed);
diff --git a/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java b/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java
index 44551a8adac6..ef7739a2e8a9 100644
--- a/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java
@@ -81,19 +81,19 @@ void containsTest() {
@Test
void sizeTest() {
Map map = getMap();
- assertEquals(map.size(), 0);
+ assertEquals(0, map.size());
for (int i = -100; i < 100; i++) {
map.put(i, String.valueOf(i));
}
- assertEquals(map.size(), 200);
+ assertEquals(200, map.size());
for (int i = -50; i < 50; i++) {
map.delete(i);
}
- assertEquals(map.size(), 100);
+ assertEquals(100, map.size());
}
@Test
diff --git a/src/test/java/com/thealgorithms/datastructures/heaps/HeapElementTest.java b/src/test/java/com/thealgorithms/datastructures/heaps/HeapElementTest.java
index d04a9de8a94b..792969200c82 100644
--- a/src/test/java/com/thealgorithms/datastructures/heaps/HeapElementTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/heaps/HeapElementTest.java
@@ -2,6 +2,7 @@
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 static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
@@ -39,7 +40,7 @@ void testEquals() {
assertEquals(element1, element2); // Same key and info
assertNotEquals(element1, element3); // Different key
- assertNotEquals(null, element1); // Check for null
+ assertNotNull(element1);
assertNotEquals("String", element1); // Check for different type
}
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..ba5614a07916
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/lists/MiddleOfLinkedListTest.java
@@ -0,0 +1,74 @@
+package com.thealgorithms.datastructures.lists;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import java.util.Objects;
+import org.junit.jupiter.api.Test;
+
+public class MiddleOfLinkedListTest {
+
+ private static SinglyLinkedListNode listOf(int firstValue, int... remainingValues) {
+ SinglyLinkedListNode head = new SinglyLinkedListNode(firstValue);
+ SinglyLinkedListNode current = head;
+
+ for (int i = 0; i < remainingValues.length; i++) {
+ current.next = new SinglyLinkedListNode(remainingValues[i]);
+ current = current.next;
+ }
+ return head;
+ }
+
+ @Test
+ void middleNodeOddLength() {
+ SinglyLinkedListNode head = listOf(1, 2, 3, 4, 5);
+ SinglyLinkedListNode middle = Objects.requireNonNull(MiddleOfLinkedList.middleNode(head));
+ assertEquals(3, middle.value);
+ }
+
+ @Test
+ void middleNodeEvenLengthReturnsSecondMiddle() {
+ SinglyLinkedListNode head = listOf(1, 2, 3, 4, 5, 6);
+ SinglyLinkedListNode middle = Objects.requireNonNull(MiddleOfLinkedList.middleNode(head));
+ assertEquals(4, middle.value);
+ }
+
+ @Test
+ void middleNodeSingleElement() {
+ SinglyLinkedListNode head = listOf(42);
+ SinglyLinkedListNode middle = Objects.requireNonNull(MiddleOfLinkedList.middleNode(head));
+ assertEquals(42, middle.value);
+ }
+
+ @Test
+ void middleNodeTwoElementsReturnsSecond() {
+ SinglyLinkedListNode head = listOf(10, 20);
+ SinglyLinkedListNode middle = Objects.requireNonNull(MiddleOfLinkedList.middleNode(head));
+ assertEquals(20, middle.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;
+
+ SinglyLinkedListNode middle = Objects.requireNonNull(MiddleOfLinkedList.middleNode(first));
+ assertEquals(3, middle.value);
+
+ assertEquals(second, first.next);
+ assertEquals(third, second.next);
+ assertEquals(fourth, third.next);
+ assertNull(fourth.next);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/queues/PriorityQueuesTest.java b/src/test/java/com/thealgorithms/datastructures/queues/PriorityQueuesTest.java
index e97fe091c556..3bb8bbabb761 100644
--- a/src/test/java/com/thealgorithms/datastructures/queues/PriorityQueuesTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/queues/PriorityQueuesTest.java
@@ -9,14 +9,14 @@ class PriorityQueuesTest {
void testPQInsertion() {
PriorityQueue myQueue = new PriorityQueue(4);
myQueue.insert(2);
- Assertions.assertEquals(myQueue.peek(), 2);
+ Assertions.assertEquals(2, myQueue.peek());
myQueue.insert(5);
myQueue.insert(3);
- Assertions.assertEquals(myQueue.peek(), 5);
+ Assertions.assertEquals(5, myQueue.peek());
myQueue.insert(10);
- Assertions.assertEquals(myQueue.peek(), 10);
+ Assertions.assertEquals(10, myQueue.peek());
}
@Test
@@ -28,32 +28,32 @@ void testPQDeletion() {
myQueue.insert(10);
myQueue.remove();
- Assertions.assertEquals(myQueue.peek(), 5);
+ Assertions.assertEquals(5, myQueue.peek());
myQueue.remove();
myQueue.remove();
- Assertions.assertEquals(myQueue.peek(), 2);
+ Assertions.assertEquals(2, myQueue.peek());
}
@Test
void testPQExtra() {
PriorityQueue myQueue = new PriorityQueue(4);
- Assertions.assertEquals(myQueue.isEmpty(), true);
- Assertions.assertEquals(myQueue.isFull(), false);
+ Assertions.assertTrue(myQueue.isEmpty());
+ Assertions.assertFalse(myQueue.isFull());
myQueue.insert(2);
myQueue.insert(5);
- Assertions.assertEquals(myQueue.isFull(), false);
+ Assertions.assertFalse(myQueue.isFull());
myQueue.insert(3);
myQueue.insert(10);
- Assertions.assertEquals(myQueue.isEmpty(), false);
- Assertions.assertEquals(myQueue.isFull(), true);
+ Assertions.assertFalse(myQueue.isEmpty());
+ Assertions.assertTrue(myQueue.isFull());
myQueue.remove();
- Assertions.assertEquals(myQueue.getSize(), 3);
- Assertions.assertEquals(myQueue.peek(), 5);
+ Assertions.assertEquals(3, myQueue.getSize());
+ Assertions.assertEquals(5, myQueue.peek());
myQueue.remove();
myQueue.remove();
- Assertions.assertEquals(myQueue.peek(), 2);
- Assertions.assertEquals(myQueue.getSize(), 1);
+ Assertions.assertEquals(2, myQueue.peek());
+ Assertions.assertEquals(1, myQueue.getSize());
}
@Test
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/TreapTest.java b/src/test/java/com/thealgorithms/datastructures/trees/TreapTest.java
index 09ada594faca..52b74a7a1faf 100644
--- a/src/test/java/com/thealgorithms/datastructures/trees/TreapTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/trees/TreapTest.java
@@ -2,6 +2,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
@@ -30,7 +31,7 @@ public void searchAndNotFound() {
treap.insert(3);
treap.insert(8);
treap.insert(1);
- assertEquals(null, treap.search(4));
+ assertNull(treap.search(4));
}
@Test
diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/LongestCommonSubsequenceTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/LongestCommonSubsequenceTest.java
index 40bbdff15ca6..91169c4cc9d8 100644
--- a/src/test/java/com/thealgorithms/dynamicprogramming/LongestCommonSubsequenceTest.java
+++ b/src/test/java/com/thealgorithms/dynamicprogramming/LongestCommonSubsequenceTest.java
@@ -1,6 +1,7 @@
package com.thealgorithms.dynamicprogramming;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
@@ -55,27 +56,24 @@ public void testLCSWithBothEmptyStrings() {
public void testLCSWithNullFirstString() {
String str1 = null;
String str2 = "XYZ";
- String expected = null; // Should return null if first string is null
String result = LongestCommonSubsequence.getLCS(str1, str2);
- assertEquals(expected, result);
+ assertNull(result);
}
@Test
public void testLCSWithNullSecondString() {
String str1 = "ABC";
String str2 = null;
- String expected = null; // Should return null if second string is null
String result = LongestCommonSubsequence.getLCS(str1, str2);
- assertEquals(expected, result);
+ assertNull(result);
}
@Test
public void testLCSWithNullBothStrings() {
String str1 = null;
String str2 = null;
- String expected = null; // Should return null if both strings are null
String result = LongestCommonSubsequence.getLCS(str1, str2);
- assertEquals(expected, result);
+ assertNull(result);
}
@Test
diff --git a/src/test/java/com/thealgorithms/io/BufferedReaderTest.java b/src/test/java/com/thealgorithms/io/BufferedReaderTest.java
index 891c3066058e..088e86f8f7c5 100644
--- a/src/test/java/com/thealgorithms/io/BufferedReaderTest.java
+++ b/src/test/java/com/thealgorithms/io/BufferedReaderTest.java
@@ -17,15 +17,15 @@ public void testPeeks() throws IOException {
BufferedReader reader = new BufferedReader(input);
// read the first letter
- assertEquals(reader.read(), 'H');
+ assertEquals('H', reader.read());
len--;
- assertEquals(reader.available(), len);
+ assertEquals(len, reader.available());
// position: H[e]llo!\nWorld!
// reader.read() will be == 'e'
- assertEquals(reader.peek(1), 'l');
- assertEquals(reader.peek(2), 'l'); // second l
- assertEquals(reader.peek(3), 'o');
+ assertEquals('l', reader.peek(1));
+ assertEquals('l', reader.peek(2)); // second l
+ assertEquals('o', reader.peek(3));
}
@Test
@@ -38,21 +38,21 @@ public void testMixes() throws IOException {
BufferedReader reader = new BufferedReader(input);
// read the first letter
- assertEquals(reader.read(), 'H'); // first letter
+ assertEquals('H', reader.read()); // first letter
len--;
- assertEquals(reader.peek(1), 'l'); // third later (second letter after 'H')
- assertEquals(reader.read(), 'e'); // second letter
+ assertEquals('l', reader.peek(1)); // third later (second letter after 'H')
+ assertEquals('e', reader.read()); // second letter
len--;
- assertEquals(reader.available(), len);
+ assertEquals(len, reader.available());
// position: H[e]llo!\nWorld!
- assertEquals(reader.peek(2), 'o'); // second l
- assertEquals(reader.peek(3), '!');
- assertEquals(reader.peek(4), '\n');
+ assertEquals('o', reader.peek(2)); // second l
+ assertEquals('!', reader.peek(3));
+ assertEquals('\n', reader.peek(4));
- assertEquals(reader.read(), 'l'); // third letter
- assertEquals(reader.peek(1), 'o'); // fourth letter
+ assertEquals('l', reader.read()); // third letter
+ assertEquals('o', reader.peek(1)); // fourth letter
for (int i = 0; i < 6; i++) {
reader.read();
@@ -74,23 +74,23 @@ public void testBlockPractical() throws IOException {
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
BufferedReader reader = new BufferedReader(input);
- assertEquals(reader.peek(), 'H');
- assertEquals(reader.read(), '!'); // read the first letter
+ assertEquals('H', reader.peek());
+ assertEquals('!', reader.read()); // read the first letter
len--;
// this only reads the next 5 bytes (Hello) because
// the default buffer size = 5
- assertEquals(new String(reader.readBlock()), "Hello");
+ assertEquals("Hello", new String(reader.readBlock()));
len -= 5;
assertEquals(reader.available(), len);
// maybe kind of a practical demonstration / use case
if (reader.read() == '\n') {
- assertEquals(reader.read(), 'W');
- assertEquals(reader.read(), 'o');
+ assertEquals('W', reader.read());
+ assertEquals('o', reader.read());
// the rest of the blocks
- assertEquals(new String(reader.readBlock()), "rld!");
+ assertEquals("rld!", new String(reader.readBlock()));
} else {
// should not reach
throw new IOException("Something not right");
diff --git a/src/test/java/com/thealgorithms/maths/BellNumbersTest.java b/src/test/java/com/thealgorithms/maths/BellNumbersTest.java
new file mode 100644
index 000000000000..8dd83cf0f7a9
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/BellNumbersTest.java
@@ -0,0 +1,53 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+class BellNumbersTest {
+
+ @Test
+ void testStandardCases() {
+ // Base cases and small numbers
+ assertEquals(1, BellNumbers.compute(0));
+ assertEquals(1, BellNumbers.compute(1));
+ assertEquals(2, BellNumbers.compute(2));
+ assertEquals(5, BellNumbers.compute(3));
+ assertEquals(15, BellNumbers.compute(4));
+ assertEquals(52, BellNumbers.compute(5));
+ }
+
+ @Test
+ void testMediumNumber() {
+ // B10 = 115,975
+ assertEquals(115975, BellNumbers.compute(10));
+ // B15 = 1,382,958,545
+ assertEquals(1382958545L, BellNumbers.compute(15));
+ }
+
+ @Test
+ void testLargeNumber() {
+ // B20 = 51,724,158,235,372
+ // We use the 'L' suffix to tell Java this is a long literal
+ assertEquals(51724158235372L, BellNumbers.compute(20));
+ }
+
+ @Test
+ void testMaxLongCapacity() {
+ // B25 is the largest Bell number that fits in a Java long (signed 64-bit)
+ // B25 = 4,638,590,332,229,999,353
+ assertEquals(4638590332229999353L, BellNumbers.compute(25));
+ }
+
+ @Test
+ void testNegativeInput() {
+ assertThrows(IllegalArgumentException.class, () -> BellNumbers.compute(-1));
+ }
+
+ @Test
+ void testOverflowProtection() {
+ // We expect an exception if the user asks for the impossible
+ assertThrows(IllegalArgumentException.class, () -> BellNumbers.compute(26));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/DistanceBetweenTwoPointsTest.java b/src/test/java/com/thealgorithms/maths/DistanceBetweenTwoPointsTest.java
new file mode 100644
index 000000000000..6bd124629740
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/DistanceBetweenTwoPointsTest.java
@@ -0,0 +1,23 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+class DistanceBetweenTwoPointsTest {
+
+ @Test
+ void testDistanceSimple() {
+ assertEquals(5.0, DistanceBetweenTwoPoints.calculate(0, 0, 3, 4), 1e-9);
+ }
+
+ @Test
+ void testDistanceNegativeCoordinates() {
+ assertEquals(5.0, DistanceBetweenTwoPoints.calculate(-1, -1, 2, 3), 1e-9);
+ }
+
+ @Test
+ void testSamePoint() {
+ assertEquals(0.0, DistanceBetweenTwoPoints.calculate(2, 2, 2, 2), 1e-9);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/DistanceFormulaTest.java b/src/test/java/com/thealgorithms/maths/DistanceFormulaTest.java
index 3a14b80dd4f9..66f3b7b03938 100644
--- a/src/test/java/com/thealgorithms/maths/DistanceFormulaTest.java
+++ b/src/test/java/com/thealgorithms/maths/DistanceFormulaTest.java
@@ -9,78 +9,78 @@ public class DistanceFormulaTest {
@Test
void euclideanTest1() {
- Assertions.assertEquals(DistanceFormula.euclideanDistance(1, 1, 2, 2), 1.4142135623730951);
+ Assertions.assertEquals(1.4142135623730951, DistanceFormula.euclideanDistance(1, 1, 2, 2));
}
@Test
void euclideanTest2() {
- Assertions.assertEquals(DistanceFormula.euclideanDistance(1, 3, 8, 0), 7.0710678118654755);
+ Assertions.assertEquals(7.0710678118654755, DistanceFormula.euclideanDistance(1, 3, 8, 0));
}
@Test
void euclideanTest3() {
- Assertions.assertEquals(DistanceFormula.euclideanDistance(2.4, 9.1, 55.1, 100), 110.91911467371168);
+ Assertions.assertEquals(110.91911467371168, DistanceFormula.euclideanDistance(2.4, 9.1, 55.1, 100));
}
@Test
void euclideanTest4() {
- Assertions.assertEquals(DistanceFormula.euclideanDistance(1000, 13, 20000, 84), 19022.067605809836);
+ Assertions.assertEquals(19022.067605809836, DistanceFormula.euclideanDistance(1000, 13, 20000, 84));
}
@Test
public void manhattantest1() {
- assertEquals(DistanceFormula.manhattanDistance(1, 2, 3, 4), 4);
+ assertEquals(4, DistanceFormula.manhattanDistance(1, 2, 3, 4));
}
@Test
public void manhattantest2() {
- assertEquals(DistanceFormula.manhattanDistance(6.5, 8.4, 20.1, 13.6), 18.8);
+ assertEquals(18.8, DistanceFormula.manhattanDistance(6.5, 8.4, 20.1, 13.6));
}
@Test
public void manhattanTest3() {
- assertEquals(DistanceFormula.manhattanDistance(10.112, 50, 8, 25.67), 26.442);
+ assertEquals(26.442, DistanceFormula.manhattanDistance(10.112, 50, 8, 25.67));
}
@Test
public void hammingTest1() {
int[] array1 = {1, 1, 1, 1};
int[] array2 = {0, 0, 0, 0};
- assertEquals(DistanceFormula.hammingDistance(array1, array2), 4);
+ assertEquals(4, DistanceFormula.hammingDistance(array1, array2));
}
@Test
public void hammingTest2() {
int[] array1 = {1, 1, 1, 1};
int[] array2 = {1, 1, 1, 1};
- assertEquals(DistanceFormula.hammingDistance(array1, array2), 0);
+ assertEquals(0, DistanceFormula.hammingDistance(array1, array2));
}
@Test
public void hammingTest3() {
int[] array1 = {1, 0, 0, 1, 1, 0, 1, 1, 0};
int[] array2 = {0, 1, 0, 0, 1, 1, 1, 0, 0};
- assertEquals(DistanceFormula.hammingDistance(array1, array2), 5);
+ assertEquals(5, DistanceFormula.hammingDistance(array1, array2));
}
@Test
public void minkowskiTest1() {
double[] array1 = {1, 3, 8, 5};
double[] array2 = {4, 2, 6, 9};
- assertEquals(DistanceFormula.minkowskiDistance(array1, array2, 1), 10);
+ assertEquals(10, DistanceFormula.minkowskiDistance(array1, array2, 1));
}
@Test
public void minkowskiTest2() {
double[] array1 = {1, 3, 8, 5};
double[] array2 = {4, 2, 6, 9};
- assertEquals(DistanceFormula.minkowskiDistance(array1, array2, 2), 5.477225575051661);
+ assertEquals(5.477225575051661, DistanceFormula.minkowskiDistance(array1, array2, 2));
}
@Test
public void minkowskiTest3() {
double[] array1 = {1, 3, 8, 5};
double[] array2 = {4, 2, 6, 9};
- assertEquals(DistanceFormula.minkowskiDistance(array1, array2, 3), 4.641588833612778);
+ assertEquals(4.641588833612778, DistanceFormula.minkowskiDistance(array1, array2, 3));
}
}
diff --git a/src/test/java/com/thealgorithms/maths/FactorialTest.java b/src/test/java/com/thealgorithms/maths/FactorialTest.java
index b38dc45589ee..3ff7097b8113 100644
--- a/src/test/java/com/thealgorithms/maths/FactorialTest.java
+++ b/src/test/java/com/thealgorithms/maths/FactorialTest.java
@@ -11,7 +11,7 @@ public class FactorialTest {
@Test
public void testWhenInvalidInoutProvidedShouldThrowException() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Factorial.factorial(-1));
- assertEquals(exception.getMessage(), EXCEPTION_MESSAGE);
+ assertEquals(EXCEPTION_MESSAGE, exception.getMessage());
}
@Test
diff --git a/src/test/java/com/thealgorithms/maths/LinearDiophantineEquationsSolverTest.java b/src/test/java/com/thealgorithms/maths/LinearDiophantineEquationsSolverTest.java
index c4205985dbfd..885382e29ca2 100644
--- a/src/test/java/com/thealgorithms/maths/LinearDiophantineEquationsSolverTest.java
+++ b/src/test/java/com/thealgorithms/maths/LinearDiophantineEquationsSolverTest.java
@@ -176,7 +176,7 @@ void testSolutionEquality() {
assertEquals(solution1, solution2);
assertNotEquals(solution3, solution1);
assertEquals(solution1, solution1);
- assertNotEquals(null, solution1);
+ assertNotNull(solution1);
assertNotEquals("string", solution1);
}
@@ -217,7 +217,7 @@ void testGcdSolutionWrapperEquality() {
assertEquals(wrapper1, wrapper2);
assertNotEquals(wrapper3, wrapper1);
assertEquals(wrapper1, wrapper1);
- assertNotEquals(null, wrapper1);
+ assertNotNull(wrapper1);
assertNotEquals("string", wrapper1);
}
diff --git a/src/test/java/com/thealgorithms/maths/NthUglyNumberTest.java b/src/test/java/com/thealgorithms/maths/NthUglyNumberTest.java
index 3fe58dadf8a5..1ee437b190c5 100644
--- a/src/test/java/com/thealgorithms/maths/NthUglyNumberTest.java
+++ b/src/test/java/com/thealgorithms/maths/NthUglyNumberTest.java
@@ -48,22 +48,22 @@ public void testGetWithSameObject() {
var uglyNumbers = new NthUglyNumber(new int[] {7, 2, 5, 3});
for (final var tc : testCases.entrySet()) {
- assertEquals(uglyNumbers.get(tc.getKey()), tc.getValue());
+ assertEquals(tc.getValue(), uglyNumbers.get(tc.getKey()));
}
- assertEquals(uglyNumbers.get(999), 385875);
+ assertEquals(385875, uglyNumbers.get(999));
}
@Test
public void testGetWithBase1() {
var uglyNumbers = new NthUglyNumber(new int[] {1});
- assertEquals(uglyNumbers.get(10), 1);
+ assertEquals(1, uglyNumbers.get(10));
}
@Test
public void testGetWithBase2() {
var uglyNumbers = new NthUglyNumber(new int[] {2});
- assertEquals(uglyNumbers.get(5), 32);
+ assertEquals(32, uglyNumbers.get(5));
}
@Test
diff --git a/src/test/java/com/thealgorithms/maths/PalindromeNumberTest.java b/src/test/java/com/thealgorithms/maths/PalindromeNumberTest.java
index a70100c0b913..4e4bd85d07b5 100644
--- a/src/test/java/com/thealgorithms/maths/PalindromeNumberTest.java
+++ b/src/test/java/com/thealgorithms/maths/PalindromeNumberTest.java
@@ -25,6 +25,6 @@ public void testNumbersAreNotPalindromes() {
@Test
public void testIfNegativeInputThenExceptionExpected() {
IllegalArgumentException exception = Assertions.assertThrows(IllegalArgumentException.class, () -> PalindromeNumber.isPalindrome(-1));
- Assertions.assertEquals(exception.getMessage(), "Input parameter must not be negative!");
+ Assertions.assertEquals("Input parameter must not be negative!", exception.getMessage());
}
}
diff --git a/src/test/java/com/thealgorithms/maths/ParseIntegerTest.java b/src/test/java/com/thealgorithms/maths/ParseIntegerTest.java
index 7649e21eb231..a9b78be88042 100644
--- a/src/test/java/com/thealgorithms/maths/ParseIntegerTest.java
+++ b/src/test/java/com/thealgorithms/maths/ParseIntegerTest.java
@@ -14,13 +14,13 @@ public class ParseIntegerTest {
@Test
public void testNullInput() {
IllegalArgumentException exception = Assertions.assertThrows(IllegalArgumentException.class, () -> ParseInteger.parseInt(null));
- Assertions.assertEquals(exception.getMessage(), NULL_PARAMETER_MESSAGE);
+ Assertions.assertEquals(NULL_PARAMETER_MESSAGE, exception.getMessage());
}
@Test
public void testEmptyInput() {
IllegalArgumentException exception = Assertions.assertThrows(IllegalArgumentException.class, () -> ParseInteger.parseInt(""));
- Assertions.assertEquals(exception.getMessage(), EMPTY_PARAMETER_MESSAGE);
+ Assertions.assertEquals(EMPTY_PARAMETER_MESSAGE, exception.getMessage());
}
@Test
diff --git a/src/test/java/com/thealgorithms/maths/QuadraticEquationSolverTest.java b/src/test/java/com/thealgorithms/maths/QuadraticEquationSolverTest.java
index a2046511ddf5..a6552d56783c 100644
--- a/src/test/java/com/thealgorithms/maths/QuadraticEquationSolverTest.java
+++ b/src/test/java/com/thealgorithms/maths/QuadraticEquationSolverTest.java
@@ -14,10 +14,10 @@ public void testSolveEquationRealRoots() {
double c = 1.9;
ComplexNumber[] roots = quadraticEquationSolver.solveEquation(a, b, c);
- Assertions.assertEquals(roots.length, 2);
- Assertions.assertEquals(roots[0].real, -0.27810465435684306);
+ Assertions.assertEquals(2, roots.length, 2);
+ Assertions.assertEquals(-0.27810465435684306, roots[0].real);
Assertions.assertNull(roots[0].imaginary);
- Assertions.assertEquals(roots[1].real, -1.6266572504050616);
+ Assertions.assertEquals(-1.6266572504050616, roots[1].real);
Assertions.assertNull(roots[1].imaginary);
}
@@ -29,8 +29,8 @@ public void testSolveEquationEqualRoots() {
double c = 1;
ComplexNumber[] roots = quadraticEquationSolver.solveEquation(a, b, c);
- Assertions.assertEquals(roots.length, 1);
- Assertions.assertEquals(roots[0].real, -1);
+ Assertions.assertEquals(1, roots.length);
+ Assertions.assertEquals(-1, roots[0].real);
}
@Test
@@ -41,10 +41,10 @@ public void testSolveEquationComplexRoots() {
double c = 5.6;
ComplexNumber[] roots = quadraticEquationSolver.solveEquation(a, b, c);
- Assertions.assertEquals(roots.length, 2);
- Assertions.assertEquals(roots[0].real, -0.8695652173913044);
- Assertions.assertEquals(roots[0].imaginary, 1.2956229935435948);
- Assertions.assertEquals(roots[1].real, -0.8695652173913044);
- Assertions.assertEquals(roots[1].imaginary, -1.2956229935435948);
+ Assertions.assertEquals(2, roots.length);
+ Assertions.assertEquals(-0.8695652173913044, roots[0].real);
+ Assertions.assertEquals(1.2956229935435948, roots[0].imaginary);
+ Assertions.assertEquals(-0.8695652173913044, roots[1].real);
+ Assertions.assertEquals(-1.2956229935435948, roots[1].imaginary);
}
}
diff --git a/src/test/java/com/thealgorithms/maths/SecondMinMaxTest.java b/src/test/java/com/thealgorithms/maths/SecondMinMaxTest.java
index c744614e5cfa..c5d47f2213a9 100644
--- a/src/test/java/com/thealgorithms/maths/SecondMinMaxTest.java
+++ b/src/test/java/com/thealgorithms/maths/SecondMinMaxTest.java
@@ -29,19 +29,19 @@ public TestCase(final int[] inInputArray, final int inSecondMin, final int inSec
@Test
public void testForEmptyInputArray() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> SecondMinMax.findSecondMin(new int[] {}));
- assertEquals(exception.getMessage(), EXP_MSG_ARR_LEN_LESS_2);
+ assertEquals(EXP_MSG_ARR_LEN_LESS_2, exception.getMessage());
}
@Test
public void testForArrayWithSingleElement() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> SecondMinMax.findSecondMax(new int[] {1}));
- assertEquals(exception.getMessage(), EXP_MSG_ARR_LEN_LESS_2);
+ assertEquals(EXP_MSG_ARR_LEN_LESS_2, exception.getMessage());
}
@Test
public void testForArrayWithSameElements() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> SecondMinMax.findSecondMin(new int[] {1, 1, 1, 1}));
- assertEquals(exception.getMessage(), EXP_MSG_ARR_SAME_ELE);
+ assertEquals(EXP_MSG_ARR_SAME_ELE, exception.getMessage());
}
@ParameterizedTest
diff --git a/src/test/java/com/thealgorithms/maths/StandardDeviationTest.java b/src/test/java/com/thealgorithms/maths/StandardDeviationTest.java
index 2c10d2d14f3e..4716d389a4ca 100644
--- a/src/test/java/com/thealgorithms/maths/StandardDeviationTest.java
+++ b/src/test/java/com/thealgorithms/maths/StandardDeviationTest.java
@@ -8,19 +8,19 @@ public class StandardDeviationTest {
@Test
void test1() {
double[] t1 = new double[] {1, 1, 1, 1, 1};
- Assertions.assertEquals(StandardDeviation.stdDev(t1), 0.0);
+ Assertions.assertEquals(0.0, StandardDeviation.stdDev(t1));
}
@Test
void test2() {
double[] t2 = new double[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
- Assertions.assertEquals(StandardDeviation.stdDev(t2), 2.8722813232690143);
+ Assertions.assertEquals(2.8722813232690143, StandardDeviation.stdDev(t2));
}
@Test
void test3() {
double[] t3 = new double[] {1.1, 8.5, 20.3, 2.4, 6.2};
- Assertions.assertEquals(StandardDeviation.stdDev(t3), 6.8308125431752265);
+ Assertions.assertEquals(6.8308125431752265, StandardDeviation.stdDev(t3));
}
@Test
@@ -32,6 +32,6 @@ void test4() {
100.00045,
56.7,
};
- Assertions.assertEquals(StandardDeviation.stdDev(t4), 38.506117353865775);
+ Assertions.assertEquals(38.506117353865775, StandardDeviation.stdDev(t4));
}
}
diff --git a/src/test/java/com/thealgorithms/maths/StandardScoreTest.java b/src/test/java/com/thealgorithms/maths/StandardScoreTest.java
index 436b1fd011c6..6858b87ad2c6 100644
--- a/src/test/java/com/thealgorithms/maths/StandardScoreTest.java
+++ b/src/test/java/com/thealgorithms/maths/StandardScoreTest.java
@@ -7,21 +7,21 @@ public class StandardScoreTest {
@Test
void test1() {
- Assertions.assertEquals(StandardScore.zScore(2, 0, 5), 0.4);
+ Assertions.assertEquals(0.4, StandardScore.zScore(2, 0, 5));
}
@Test
void test2() {
- Assertions.assertEquals(StandardScore.zScore(1, 1, 1), 0.0);
+ Assertions.assertEquals(0.0, StandardScore.zScore(1, 1, 1));
}
@Test
void test3() {
- Assertions.assertEquals(StandardScore.zScore(2.5, 1.8, 0.7), 1.0);
+ Assertions.assertEquals(1.0, StandardScore.zScore(2.5, 1.8, 0.7));
}
@Test
void test4() {
- Assertions.assertEquals(StandardScore.zScore(8.9, 3, 4.2), 1.4047619047619049);
+ Assertions.assertEquals(1.4047619047619049, StandardScore.zScore(8.9, 3, 4.2));
}
}
diff --git a/src/test/java/com/thealgorithms/maths/VolumeTest.java b/src/test/java/com/thealgorithms/maths/VolumeTest.java
index 7cd0c6716147..af882eef7563 100644
--- a/src/test/java/com/thealgorithms/maths/VolumeTest.java
+++ b/src/test/java/com/thealgorithms/maths/VolumeTest.java
@@ -1,6 +1,6 @@
package com.thealgorithms.maths;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
@@ -10,30 +10,30 @@ public class VolumeTest {
public void volume() {
/* test cube */
- assertTrue(Volume.volumeCube(7) == 343.0);
+ assertEquals(343.0, Volume.volumeCube(7));
/* test cuboid */
- assertTrue(Volume.volumeCuboid(2, 5, 7) == 70.0);
+ assertEquals(70.0, Volume.volumeCuboid(2, 5, 7));
/* test sphere */
- assertTrue(Volume.volumeSphere(7) == 1436.7550402417319);
+ assertEquals(1436.7550402417319, Volume.volumeSphere(7));
/* test cylinder */
- assertTrue(Volume.volumeCylinder(3, 7) == 197.92033717615698);
+ assertEquals(197.92033717615698, Volume.volumeCylinder(3, 7));
/* test hemisphere */
- assertTrue(Volume.volumeHemisphere(7) == 718.3775201208659);
+ assertEquals(718.3775201208659, Volume.volumeHemisphere(7));
/* test cone */
- assertTrue(Volume.volumeCone(3, 7) == 65.97344572538566);
+ assertEquals(65.97344572538566, Volume.volumeCone(3, 7));
/* test prism */
- assertTrue(Volume.volumePrism(10, 2) == 20.0);
+ assertEquals(20.0, Volume.volumePrism(10, 2));
/* test pyramid */
- assertTrue(Volume.volumePyramid(10, 3) == 10.0);
+ assertEquals(10.0, Volume.volumePyramid(10, 3));
/* test frustum */
- assertTrue(Volume.volumeFrustumOfCone(3, 5, 7) == 359.188760060433);
+ assertEquals(359.188760060433, Volume.volumeFrustumOfCone(3, 5, 7));
}
}
diff --git a/src/test/java/com/thealgorithms/misc/MedianOfRunningArrayTest.java b/src/test/java/com/thealgorithms/misc/MedianOfRunningArrayTest.java
index f41953035846..c4a74af0ba8b 100644
--- a/src/test/java/com/thealgorithms/misc/MedianOfRunningArrayTest.java
+++ b/src/test/java/com/thealgorithms/misc/MedianOfRunningArrayTest.java
@@ -17,7 +17,7 @@ public class MedianOfRunningArrayTest {
public void testWhenInvalidInoutProvidedShouldThrowException() {
var stream = new MedianOfRunningArrayInteger();
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, stream::getMedian);
- assertEquals(exception.getMessage(), EXCEPTION_MESSAGE);
+ assertEquals(EXCEPTION_MESSAGE, exception.getMessage());
}
@Test
diff --git a/src/test/java/com/thealgorithms/misc/ShuffleArrayTest.java b/src/test/java/com/thealgorithms/misc/ShuffleArrayTest.java
index 915b83e376b6..c1adafa18d9f 100644
--- a/src/test/java/com/thealgorithms/misc/ShuffleArrayTest.java
+++ b/src/test/java/com/thealgorithms/misc/ShuffleArrayTest.java
@@ -1,6 +1,7 @@
package com.thealgorithms.misc;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -67,7 +68,7 @@ void testShuffleRetainsElements() {
ShuffleArray.shuffle(arr);
// Check that the shuffled array contains the same elements
- assertTrue(arr.length == 5);
+ assertEquals(5, arr.length);
for (int i = 1; i <= 5; i++) {
assertTrue(contains(arr, i));
}
diff --git a/src/test/java/com/thealgorithms/others/NewManShanksPrimeTest.java b/src/test/java/com/thealgorithms/others/NewManShanksPrimeTest.java
deleted file mode 100644
index 3b657e441b1c..000000000000
--- a/src/test/java/com/thealgorithms/others/NewManShanksPrimeTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.thealgorithms.others;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import com.thealgorithms.dynamicprogramming.NewManShanksPrime;
-import org.junit.jupiter.api.Test;
-
-public class NewManShanksPrimeTest {
-
- @Test
- void testOne() {
- assertTrue(NewManShanksPrime.nthManShanksPrime(1, 1));
- }
-
- @Test
- void testTwo() {
- assertTrue(NewManShanksPrime.nthManShanksPrime(2, 3));
- }
-
- @Test
- void testThree() {
- assertTrue(NewManShanksPrime.nthManShanksPrime(3, 7));
- }
-
- @Test
- void testFour() {
- assertTrue(NewManShanksPrime.nthManShanksPrime(4, 17));
- }
-
- @Test
- void testFive() {
- assertTrue(NewManShanksPrime.nthManShanksPrime(5, 41));
- }
-
- @Test
- void testSix() {
- assertTrue(NewManShanksPrime.nthManShanksPrime(6, 99));
- }
-
- @Test
- void testSeven() {
- assertTrue(NewManShanksPrime.nthManShanksPrime(7, 239));
- }
-
- @Test
- void testEight() {
- assertTrue(NewManShanksPrime.nthManShanksPrime(8, 577));
- }
-}
diff --git a/src/test/java/com/thealgorithms/others/PasswordGenTest.java b/src/test/java/com/thealgorithms/others/PasswordGenTest.java
index 76492556e75f..4dcdf6b9cf4f 100644
--- a/src/test/java/com/thealgorithms/others/PasswordGenTest.java
+++ b/src/test/java/com/thealgorithms/others/PasswordGenTest.java
@@ -17,7 +17,7 @@ public void failGenerationWithSameMinMaxLengthTest() {
@Test
public void generateOneCharacterPassword() {
String tempPassword = PasswordGen.generatePassword(1, 2);
- assertTrue(tempPassword.length() == 1);
+ assertEquals(1, tempPassword.length());
}
@Test
diff --git a/src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java b/src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java
deleted file mode 100644
index 669f928cd247..000000000000
--- a/src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.thealgorithms.others.cn;
-
-import org.assertj.core.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-public class HammingDistanceTest {
- @Test
- public void checkForDifferentBits() {
- int answer = HammingDistance.compute("000", "011");
- Assertions.assertThat(answer).isEqualTo(2);
- }
-
- /*
-
- 1 0 1 0 1
- 1 1 1 1 0
- ----------
- 0 1 0 1 1
-
-
- */
- @Test
- public void checkForDifferentBitsLength() {
- int answer = HammingDistance.compute("10101", "11110");
- Assertions.assertThat(answer).isEqualTo(3);
- }
-
- @Test
- public void checkForSameBits() {
- String someBits = "111";
- int answer = HammingDistance.compute(someBits, someBits);
- Assertions.assertThat(answer).isEqualTo(0);
- }
-
- @Test
- public void checkForLongDataBits() {
- int answer = HammingDistance.compute("10010101101010000100110100", "00110100001011001100110101");
- Assertions.assertThat(answer).isEqualTo(7);
- }
-
- @Test
- public void mismatchDataBits() {
- Exception ex = org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> { HammingDistance.compute("100010", "00011"); });
-
- Assertions.assertThat(ex.getMessage()).contains("must have the same length");
- }
-
- @Test
- public void mismatchDataBits2() {
- Exception ex = org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> { HammingDistance.compute("1", "11"); });
-
- Assertions.assertThat(ex.getMessage()).contains("must have the same length");
- }
-
- @Test
- public void checkForLongDataBitsSame() {
- String someBits = "10010101101010000100110100";
- int answer = HammingDistance.compute(someBits, someBits);
- Assertions.assertThat(answer).isEqualTo(0);
- }
-
- @Test
- public void checkForEmptyInput() {
- String someBits = "";
- int answer = HammingDistance.compute(someBits, someBits);
- Assertions.assertThat(answer).isEqualTo(0);
- }
-
- @Test
- public void checkForInputOfLength1() {
- String someBits = "0";
- int answer = HammingDistance.compute(someBits, someBits);
- Assertions.assertThat(answer).isEqualTo(0);
- }
-
- @Test
- public void computeThrowsExceptionWhenInputsAreNotBitStrs() {
- Exception ex = org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> { HammingDistance.compute("1A", "11"); });
-
- Assertions.assertThat(ex.getMessage()).contains("must be a binary string");
- }
-}
diff --git a/src/test/java/com/thealgorithms/prefixsum/DifferenceArrayTest.java b/src/test/java/com/thealgorithms/prefixsum/DifferenceArrayTest.java
new file mode 100644
index 000000000000..88a480f25f1a
--- /dev/null
+++ b/src/test/java/com/thealgorithms/prefixsum/DifferenceArrayTest.java
@@ -0,0 +1,110 @@
+package com.thealgorithms.prefixsum;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+class DifferenceArrayTest {
+
+ @Test
+ void testStandardRangeUpdate() {
+ int[] input = {10, 20, 30, 40, 50};
+ DifferenceArray da = new DifferenceArray(input);
+
+ da.update(1, 3, 5);
+
+ long[] expected = {10, 25, 35, 45, 50};
+ assertArrayEquals(expected, da.getResultArray());
+ }
+
+ @Test
+ void testMultipleOverlappingUpdates() {
+ int[] input = {10, 10, 10, 10, 10};
+ DifferenceArray da = new DifferenceArray(input);
+
+ da.update(0, 2, 10);
+ da.update(2, 4, 20);
+
+ long[] expected = {20, 20, 40, 30, 30};
+ assertArrayEquals(expected, da.getResultArray());
+ }
+
+ @Test
+ void testIntegerOverflowSafety() {
+ int[] input = {Integer.MAX_VALUE, 100};
+ DifferenceArray da = new DifferenceArray(input);
+
+ da.update(0, 0, 100);
+
+ long[] result = da.getResultArray();
+ long expectedVal = (long) Integer.MAX_VALUE + 100;
+
+ assertEquals(expectedVal, result[0]);
+ }
+
+ @Test
+ void testFullRangeUpdate() {
+ int[] input = {1, 2, 3};
+ DifferenceArray da = new DifferenceArray(input);
+
+ da.update(0, 2, 100);
+
+ long[] expected = {101, 102, 103};
+ assertArrayEquals(expected, da.getResultArray());
+ }
+
+ @Test
+ void testBoundaryWriteOptimization() {
+ int[] input = {5, 5};
+ DifferenceArray da = new DifferenceArray(input);
+
+ da.update(1, 1, 5);
+
+ long[] expected = {5, 10};
+
+ assertArrayEquals(expected, da.getResultArray());
+ }
+
+ @Test
+ void testLargeMassiveUpdate() {
+ int[] input = {0};
+ DifferenceArray da = new DifferenceArray(input);
+
+ int iterations = 100000;
+ for (int i = 0; i < iterations; i++) {
+ da.update(0, 0, 1);
+ }
+
+ assertEquals(100000L, da.getResultArray()[0]);
+ }
+
+ @Test
+ void testNullInputThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> new DifferenceArray(null));
+ }
+
+ @Test
+ void testEmptyInputThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> new DifferenceArray(new int[] {}));
+ }
+
+ @Test
+ void testInvalidRangeNegativeIndex() {
+ DifferenceArray da = new DifferenceArray(new int[] {1, 2, 3});
+ assertThrows(IllegalArgumentException.class, () -> da.update(-1, 1, 5));
+ }
+
+ @Test
+ void testInvalidRangeOutOfBounds() {
+ DifferenceArray da = new DifferenceArray(new int[] {1, 2, 3});
+ assertThrows(IllegalArgumentException.class, () -> da.update(0, 3, 5));
+ }
+
+ @Test
+ void testInvalidRangeStartGreaterThanEnd() {
+ DifferenceArray da = new DifferenceArray(new int[] {1, 2, 3});
+ assertThrows(IllegalArgumentException.class, () -> da.update(2, 1, 5));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/prefixsum/PrefixSum2DTest.java b/src/test/java/com/thealgorithms/prefixsum/PrefixSum2DTest.java
new file mode 100644
index 000000000000..87feff859356
--- /dev/null
+++ b/src/test/java/com/thealgorithms/prefixsum/PrefixSum2DTest.java
@@ -0,0 +1,92 @@
+package com.thealgorithms.prefixsum;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class PrefixSum2DTest {
+
+ @Test
+ @DisplayName("Test basic 3x3 square matrix")
+ void testStandardSquare() {
+ int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
+ PrefixSum2D ps = new PrefixSum2D(matrix);
+
+ // Sum of top-left 2x2: {1,2, 4,5} -> 12
+ assertEquals(12L, ps.sumRegion(0, 0, 1, 1));
+ // Sum of bottom-right 2x2: {5,6, 8,9} -> 28
+ assertEquals(28L, ps.sumRegion(1, 1, 2, 2));
+ // Full matrix -> 45
+ assertEquals(45L, ps.sumRegion(0, 0, 2, 2));
+ }
+
+ @Test
+ @DisplayName("Test rectangular matrix (more cols than rows)")
+ void testRectangularWide() {
+ int[][] matrix = {{1, 1, 1, 1}, {2, 2, 2, 2}};
+ PrefixSum2D ps = new PrefixSum2D(matrix);
+
+ // Sum of first 3 columns of both rows -> (1*3) + (2*3) = 9
+ assertEquals(9L, ps.sumRegion(0, 0, 1, 2));
+ }
+
+ @Test
+ @DisplayName("Test rectangular matrix (more rows than cols)")
+ void testRectangularTall() {
+ int[][] matrix = {{1}, {2}, {3}, {4}};
+ PrefixSum2D ps = new PrefixSum2D(matrix);
+
+ // Sum of middle two elements -> 2+3 = 5
+ assertEquals(5L, ps.sumRegion(1, 0, 2, 0));
+ }
+
+ @Test
+ @DisplayName("Test single element matrix")
+ void testSingleElement() {
+ int[][] matrix = {{100}};
+ PrefixSum2D ps = new PrefixSum2D(matrix);
+
+ assertEquals(100L, ps.sumRegion(0, 0, 0, 0));
+ }
+
+ @Test
+ @DisplayName("Test large numbers for overflow (Integer -> Long)")
+ void testLargeNumbers() {
+ // 2 billion. Two of these sum to > MAX_INT
+ int val = 2_000_000_000;
+ int[][] matrix = {{val, val}, {val, val}};
+ PrefixSum2D ps = new PrefixSum2D(matrix);
+
+ // 4 * 2B = 8 Billion
+ assertEquals(8_000_000_000L, ps.sumRegion(0, 0, 1, 1));
+ }
+
+ @Test
+ @DisplayName("Test invalid inputs")
+ void testInvalidInputs() {
+ assertThrows(IllegalArgumentException.class, () -> new PrefixSum2D(null));
+ assertThrows(IllegalArgumentException.class, () -> new PrefixSum2D(new int[][] {})); // empty
+ assertThrows(IllegalArgumentException.class, () -> new PrefixSum2D(new int[][] {{}})); // empty row
+ }
+
+ @Test
+ @DisplayName("Test invalid query ranges")
+ void testInvalidRanges() {
+ int[][] matrix = {{1, 2}, {3, 4}};
+ PrefixSum2D ps = new PrefixSum2D(matrix);
+
+ // Negative indices
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRegion(-1, 0, 0, 0));
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRegion(0, -1, 0, 0));
+
+ // Out of bounds
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRegion(0, 0, 2, 0)); // row2 too big
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRegion(0, 0, 0, 2)); // col2 too big
+
+ // Inverted ranges (start > end)
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRegion(1, 0, 0, 0)); // row1 > row2
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRegion(0, 1, 0, 0)); // col1 > col2
+ }
+}
diff --git a/src/test/java/com/thealgorithms/prefixsum/PrefixSumTest.java b/src/test/java/com/thealgorithms/prefixsum/PrefixSumTest.java
new file mode 100644
index 000000000000..a421b62e9306
--- /dev/null
+++ b/src/test/java/com/thealgorithms/prefixsum/PrefixSumTest.java
@@ -0,0 +1,80 @@
+package com.thealgorithms.prefixsum;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class PrefixSumTest {
+
+ @Test
+ @DisplayName("Test basic sum with positive integers")
+ void testStandardCase() {
+ int[] input = {1, 2, 3, 4, 5};
+ PrefixSum ps = new PrefixSum(input);
+
+ // Sum of range [0, 4] -> 15
+ assertEquals(15L, ps.sumRange(0, 4));
+
+ // Sum of range [1, 3] -> 9
+ assertEquals(9L, ps.sumRange(1, 3));
+ }
+
+ @Test
+ @DisplayName("Test array with negative numbers and zeros")
+ void testNegativeAndZeros() {
+ int[] input = {-2, 0, 3, -5, 2, -1};
+ PrefixSum ps = new PrefixSum(input);
+
+ assertEquals(1L, ps.sumRange(0, 2));
+ assertEquals(-1L, ps.sumRange(2, 5));
+ assertEquals(0L, ps.sumRange(1, 1));
+ }
+
+ @Test
+ @DisplayName("Test with large integers to verify overflow handling")
+ void testLargeNumbers() {
+ // Two values that fit in int, but their sum exceeds Integer.MAX_VALUE
+ // Integer.MAX_VALUE is approx 2.14 billion.
+ int val = 2_000_000_000;
+ int[] input = {val, val, val};
+ PrefixSum ps = new PrefixSum(input);
+
+ // Sum of three 2 billion values is 6 billion (fits in long, overflows int)
+ assertEquals(6_000_000_000L, ps.sumRange(0, 2));
+ }
+
+ @Test
+ @DisplayName("Test single element array")
+ void testSingleElement() {
+ int[] input = {42};
+ PrefixSum ps = new PrefixSum(input);
+ assertEquals(42L, ps.sumRange(0, 0));
+ }
+
+ @Test
+ @DisplayName("Test constructor with null input")
+ void testNullInput() {
+ assertThrows(IllegalArgumentException.class, () -> new PrefixSum(null));
+ }
+
+ @Test
+ @DisplayName("Test empty array behavior")
+ void testEmptyArray() {
+ int[] input = {};
+ PrefixSum ps = new PrefixSum(input);
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRange(0, 0));
+ }
+
+ @Test
+ @DisplayName("Test invalid range indices")
+ void testInvalidIndices() {
+ int[] input = {10, 20, 30};
+ PrefixSum ps = new PrefixSum(input);
+
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRange(-1, 1));
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRange(0, 3));
+ assertThrows(IndexOutOfBoundsException.class, () -> ps.sumRange(2, 1));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/prefixsum/SubarraySumEqualskTest.java b/src/test/java/com/thealgorithms/prefixsum/SubarraySumEqualskTest.java
new file mode 100644
index 000000000000..68f85b713046
--- /dev/null
+++ b/src/test/java/com/thealgorithms/prefixsum/SubarraySumEqualskTest.java
@@ -0,0 +1,59 @@
+package com.thealgorithms.prefixsum;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for {@link SubarraySumEqualsK}.
+ */
+class SubarraySumEqualsKTest {
+
+ @Test
+ void testBasicExample() {
+ int[] nums = {1, 1, 1};
+ int k = 2;
+ assertEquals(2, SubarraySumEqualsK.countSubarrays(nums, k));
+ }
+
+ @Test
+ void testWithNegativeNumbers() {
+ int[] nums = {1, -1, 0};
+ int k = 0;
+ assertEquals(3, SubarraySumEqualsK.countSubarrays(nums, k));
+ }
+
+ @Test
+ void testSingleElementEqualToK() {
+ int[] nums = {5};
+ int k = 5;
+ assertEquals(1, SubarraySumEqualsK.countSubarrays(nums, k));
+ }
+
+ @Test
+ void testSingleElementNotEqualToK() {
+ int[] nums = {5};
+ int k = 3;
+ assertEquals(0, SubarraySumEqualsK.countSubarrays(nums, k));
+ }
+
+ @Test
+ void testAllZeros() {
+ int[] nums = {0, 0, 0};
+ int k = 0;
+ assertEquals(6, SubarraySumEqualsK.countSubarrays(nums, k));
+ }
+
+ @Test
+ void testEmptyArray() {
+ int[] nums = {};
+ int k = 0;
+ assertEquals(0, SubarraySumEqualsK.countSubarrays(nums, k));
+ }
+
+ @Test
+ void testNullArrayThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> SubarraySumEqualsK.countSubarrays(null, 0));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java b/src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java
index 18f0afc6a0a6..dec2c86de9c7 100644
--- a/src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java
+++ b/src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java
@@ -117,7 +117,7 @@ public void binarySearch2dArrayTestTargetInMiddle() {
int target = 8;
// Assert that the requirement, that the target is in the middle row and middle column, is
// fulfilled.
- assertEquals(arr[arr.length / 2][arr[0].length / 2], target);
+ assertEquals(target, arr[arr.length / 2][arr[0].length / 2]);
int[] ans = BinarySearch2dArray.binarySearch(arr, target);
System.out.println(Arrays.toString(ans));
assertEquals(1, ans[0]);
@@ -135,8 +135,8 @@ public void binarySearch2dArrayTestTargetAboveMiddleRowInMiddleColumn() {
// Assert that the requirement, that he target is in the middle column,
// in an array with an even number of columns, and on the row "above" the middle row.
- assertEquals(arr[0].length % 2, 0);
- assertEquals(arr[arr.length / 2 - 1][arr[0].length / 2], target);
+ assertEquals(0, arr[0].length % 2);
+ assertEquals(target, arr[arr.length / 2 - 1][arr[0].length / 2]);
int[] ans = BinarySearch2dArray.binarySearch(arr, target);
System.out.println(Arrays.toString(ans));
assertEquals(0, ans[0]);
diff --git a/src/test/java/com/thealgorithms/searches/KMPSearchTest.java b/src/test/java/com/thealgorithms/searches/KMPSearchTest.java
index cb804ac6a6a3..216c5fcd7d2c 100644
--- a/src/test/java/com/thealgorithms/searches/KMPSearchTest.java
+++ b/src/test/java/com/thealgorithms/searches/KMPSearchTest.java
@@ -14,7 +14,7 @@ public void kmpSearchTestLast() {
KMPSearch kmpSearch = new KMPSearch();
int value = kmpSearch.kmpSearch(pat, txt);
System.out.println(value);
- assertEquals(value, 10);
+ assertEquals(10, value);
}
@Test
@@ -25,7 +25,7 @@ public void kmpSearchTestFront() {
KMPSearch kmpSearch = new KMPSearch();
int value = kmpSearch.kmpSearch(pat, txt);
System.out.println(value);
- assertEquals(value, 0);
+ assertEquals(0, value);
}
@Test
@@ -36,7 +36,7 @@ public void kmpSearchTestMiddle() {
KMPSearch kmpSearch = new KMPSearch();
int value = kmpSearch.kmpSearch(pat, txt);
System.out.println(value);
- assertEquals(value, 4);
+ assertEquals(4, value);
}
@Test
@@ -47,7 +47,7 @@ public void kmpSearchTestNotFound() {
KMPSearch kmpSearch = new KMPSearch();
int value = kmpSearch.kmpSearch(pat, txt);
System.out.println(value);
- assertEquals(value, 4);
+ assertEquals(4, value);
}
@Test
@@ -58,6 +58,6 @@ public void kmpSearchTest4() {
KMPSearch kmpSearch = new KMPSearch();
int value = kmpSearch.kmpSearch(pat, txt);
System.out.println(value);
- assertEquals(value, -1);
+ assertEquals(-1, value);
}
}
diff --git a/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java b/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java
deleted file mode 100644
index 6eab20f45467..000000000000
--- a/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.thealgorithms.searches;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import org.junit.jupiter.api.Test;
-
-/**
- * @author D Sunil (https://github.com/sunilnitdgp)
- * @see PerfectBinarySearch
- */
-public class PerfectBinarySearchTest {
-
- @Test
- public void testIntegerBinarySearch() {
- Integer[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
- PerfectBinarySearch binarySearch = new PerfectBinarySearch<>();
-
- // Test cases for elements present in the array
- assertEquals(0, binarySearch.find(array, 1)); // First element
- assertEquals(4, binarySearch.find(array, 5)); // Middle element
- assertEquals(9, binarySearch.find(array, 10)); // Last element
- assertEquals(6, binarySearch.find(array, 7)); // Element in the middle
-
- // Test cases for elements not in the array
- assertEquals(-1, binarySearch.find(array, 0)); // Element before the array
- assertEquals(-1, binarySearch.find(array, 11)); // Element after the array
- assertEquals(-1, binarySearch.find(array, 100)); // Element not in the array
- }
-
- @Test
- public void testStringBinarySearch() {
- String[] array = {"apple", "banana", "cherry", "date", "fig"};
- PerfectBinarySearch binarySearch = new PerfectBinarySearch<>();
-
- // Test cases for elements not in the array
- assertEquals(-1, binarySearch.find(array, "apricot")); // Element not in the array
- assertEquals(-1, binarySearch.find(array, "bananaa")); // Element not in the array
-
- // Test cases for elements present in the array
- assertEquals(0, binarySearch.find(array, "apple")); // First element
- assertEquals(2, binarySearch.find(array, "cherry")); // Middle element
- assertEquals(4, binarySearch.find(array, "fig")); // Last element
- }
-}
diff --git a/src/test/java/com/thealgorithms/searches/QuickSelectTest.java b/src/test/java/com/thealgorithms/searches/QuickSelectTest.java
index cf160b0ff4b5..4c96be76861a 100644
--- a/src/test/java/com/thealgorithms/searches/QuickSelectTest.java
+++ b/src/test/java/com/thealgorithms/searches/QuickSelectTest.java
@@ -172,7 +172,7 @@ void quickSelect70thPercentileOfManyElements() {
void quickSelectMedianOfThreeCharacters() {
List elements = Arrays.asList('X', 'Z', 'Y');
char actual = QuickSelect.select(elements, 1);
- assertEquals(actual, 'Y');
+ assertEquals('Y', actual);
}
@Test
diff --git a/src/test/java/com/thealgorithms/searches/RotatedBinarySearchTest.java b/src/test/java/com/thealgorithms/searches/RotatedBinarySearchTest.java
new file mode 100644
index 000000000000..1e6ab4c37fcc
--- /dev/null
+++ b/src/test/java/com/thealgorithms/searches/RotatedBinarySearchTest.java
@@ -0,0 +1,53 @@
+package com.thealgorithms.searches;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+class RotatedBinarySearchTest {
+
+ @Test
+ void shouldFindElementInRotatedArrayLeftSide() {
+ RotatedBinarySearch search = new RotatedBinarySearch();
+ Integer[] array = {8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7};
+ assertEquals(2, search.find(array, 10));
+ }
+
+ @Test
+ void shouldFindElementInRotatedArrayRightSide() {
+ RotatedBinarySearch search = new RotatedBinarySearch();
+ Integer[] array = {8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7};
+ assertEquals(6, search.find(array, 2));
+ }
+
+ @Test
+ void shouldFindElementInNotRotatedArray() {
+ RotatedBinarySearch search = new RotatedBinarySearch();
+ Integer[] array = {1, 2, 3, 4, 5, 6, 7};
+ assertEquals(4, search.find(array, 5));
+ }
+
+ @Test
+ void shouldReturnMinusOneWhenNotFound() {
+ RotatedBinarySearch search = new RotatedBinarySearch();
+ Integer[] array = {4, 5, 6, 7, 0, 1, 2};
+ assertEquals(-1, search.find(array, 3));
+ }
+
+ @Test
+ void shouldHandleWhenMiddleIsGreaterThanKeyInRightSortedHalf() {
+ RotatedBinarySearch search = new RotatedBinarySearch();
+ Integer[] array = {6, 7, 0, 1, 2, 3, 4, 5};
+ assertEquals(2, search.find(array, 0));
+ }
+
+ @Test
+ void shouldHandleDuplicates() {
+ RotatedBinarySearch search = new RotatedBinarySearch();
+ Integer[] array = {2, 2, 2, 3, 4, 2};
+ int index = search.find(array, 3);
+ assertTrue(index >= 0 && index < array.length);
+ assertEquals(3, array[index]);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearchTest.java b/src/test/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearchTest.java
deleted file mode 100644
index e2917733d1d9..000000000000
--- a/src/test/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearchTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.thealgorithms.searches;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import org.junit.jupiter.api.Test;
-
-public class SortOrderAgnosticBinarySearchTest {
-
- @Test
- public void testAscending() {
- int[] arr = {1, 2, 3, 4, 5}; // for ascending order.
- int target = 2;
- int ans = SortOrderAgnosticBinarySearch.find(arr, target);
- int excepted = 1;
- assertEquals(excepted, ans);
- }
-
- @Test
- public void testDescending() {
- int[] arr = {5, 4, 3, 2, 1}; // for descending order.
- int target = 2;
- int ans = SortOrderAgnosticBinarySearch.find(arr, target);
- int excepted = 3;
- assertEquals(excepted, ans);
- }
-}
diff --git a/src/test/java/com/thealgorithms/slidingwindow/CountNiceSubarraysTest.java b/src/test/java/com/thealgorithms/slidingwindow/CountNiceSubarraysTest.java
new file mode 100644
index 000000000000..71bf24cc9e30
--- /dev/null
+++ b/src/test/java/com/thealgorithms/slidingwindow/CountNiceSubarraysTest.java
@@ -0,0 +1,55 @@
+package com.thealgorithms.slidingwindow;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class CountNiceSubarraysTest {
+ @Test
+ void testExampleCase() {
+ int[] nums = {1, 1, 2, 1, 1};
+ assertEquals(2, CountNiceSubarrays.countNiceSubarrays(nums, 3));
+ }
+
+ @Test
+ void testAllEvenNumbers() {
+ int[] nums = {2, 4, 6, 8};
+ assertEquals(0, CountNiceSubarrays.countNiceSubarrays(nums, 1));
+ }
+
+ @Test
+ void testSingleOdd() {
+ int[] nums = {1};
+ assertEquals(1, CountNiceSubarrays.countNiceSubarrays(nums, 1));
+ }
+
+ @Test
+ void testMultipleChoices() {
+ int[] nums = {2, 2, 1, 2, 2, 1, 2};
+ assertEquals(6, CountNiceSubarrays.countNiceSubarrays(nums, 2));
+ }
+
+ @Test
+ void testTrailingEvenNumbers() {
+ int[] nums = {1, 2, 2, 2};
+ assertEquals(4, CountNiceSubarrays.countNiceSubarrays(nums, 1));
+ }
+
+ @Test
+ void testMultipleWindowShrinks() {
+ int[] nums = {1, 1, 1, 1};
+ assertEquals(3, CountNiceSubarrays.countNiceSubarrays(nums, 2));
+ }
+
+ @Test
+ void testEvensBetweenOdds() {
+ int[] nums = {2, 1, 2, 1, 2};
+ assertEquals(4, CountNiceSubarrays.countNiceSubarrays(nums, 2));
+ }
+
+ @Test
+ void testShrinkWithTrailingEvens() {
+ int[] nums = {2, 2, 1, 2, 2, 1, 2, 2};
+ assertEquals(9, CountNiceSubarrays.countNiceSubarrays(nums, 2));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/sorts/SmoothSortTest.java b/src/test/java/com/thealgorithms/sorts/SmoothSortTest.java
new file mode 100644
index 000000000000..8df0502e80e7
--- /dev/null
+++ b/src/test/java/com/thealgorithms/sorts/SmoothSortTest.java
@@ -0,0 +1,8 @@
+package com.thealgorithms.sorts;
+
+public class SmoothSortTest extends SortingAlgorithmTest {
+ @Override
+ SortAlgorithm getSortAlgorithm() {
+ return new SmoothSort();
+ }
+}
diff --git a/src/test/java/com/thealgorithms/sorts/TopologicalSortTest.java b/src/test/java/com/thealgorithms/sorts/TopologicalSortTest.java
index d5588b2b968e..e19f5b928263 100644
--- a/src/test/java/com/thealgorithms/sorts/TopologicalSortTest.java
+++ b/src/test/java/com/thealgorithms/sorts/TopologicalSortTest.java
@@ -58,7 +58,7 @@ public void failureTest() {
Exception exception = assertThrows(RuntimeException.class, () -> TopologicalSort.sort(graph));
String expected = "This graph contains a cycle. No linear ordering is possible. "
+ "Back edge: 6 -> 2";
- assertEquals(exception.getMessage(), expected);
+ assertEquals(expected, exception.getMessage());
}
@Test
void testEmptyGraph() {
diff --git a/src/test/java/com/thealgorithms/sorts/TournamentSortTest.java b/src/test/java/com/thealgorithms/sorts/TournamentSortTest.java
new file mode 100644
index 000000000000..91da746447a8
--- /dev/null
+++ b/src/test/java/com/thealgorithms/sorts/TournamentSortTest.java
@@ -0,0 +1,19 @@
+package com.thealgorithms.sorts;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.Test;
+
+public class TournamentSortTest extends SortingAlgorithmTest {
+
+ @Test
+ void shouldAcceptWhenNullArrayIsPassed() {
+ Integer[] array = null;
+ assertNull(getSortAlgorithm().sort(array));
+ }
+
+ @Override
+ SortAlgorithm getSortAlgorithm() {
+ return new TournamentSort();
+ }
+}
diff --git a/src/test/java/com/thealgorithms/strings/KMPTest.java b/src/test/java/com/thealgorithms/strings/KMPTest.java
new file mode 100644
index 000000000000..9fa5f398d420
--- /dev/null
+++ b/src/test/java/com/thealgorithms/strings/KMPTest.java
@@ -0,0 +1,29 @@
+package com.thealgorithms.strings;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class KMPTest {
+
+ @Test
+ public void testNullInputs() {
+ assertEquals(List.of(), KMP.kmpMatcher(null, "A"));
+ assertEquals(List.of(), KMP.kmpMatcher("A", null));
+ assertEquals(List.of(), KMP.kmpMatcher(null, null));
+ }
+
+ @Test
+ public void testKMPMatcher() {
+ assertEquals(List.of(0, 1), KMP.kmpMatcher("AAAAABAAABA", "AAAA"));
+ assertEquals(List.of(0, 3), KMP.kmpMatcher("ABCABC", "ABC"));
+ assertEquals(List.of(10), KMP.kmpMatcher("ABABDABACDABABCABAB", "ABABCABAB"));
+ assertEquals(List.of(), KMP.kmpMatcher("ABCDE", "FGH"));
+ assertEquals(List.of(), KMP.kmpMatcher("A", "AA"));
+ assertEquals(List.of(0, 1, 2), KMP.kmpMatcher("AAA", "A"));
+ assertEquals(List.of(0), KMP.kmpMatcher("A", "A"));
+ assertEquals(List.of(), KMP.kmpMatcher("", "A"));
+ assertEquals(List.of(), KMP.kmpMatcher("A", ""));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/strings/LongestPalindromicSubstringTest.java b/src/test/java/com/thealgorithms/strings/LongestPalindromicSubstringTest.java
deleted file mode 100644
index aa13c0f4a474..000000000000
--- a/src/test/java/com/thealgorithms/strings/LongestPalindromicSubstringTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.thealgorithms.strings;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.stream.Stream;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-
-class LongestPalindromicSubstringTest {
-
- @ParameterizedTest
- @MethodSource("provideTestCasesForLongestPalindrome")
- void testLongestPalindrome(String input, String expected) {
- assertEquals(expected, LongestPalindromicSubstring.longestPalindrome(input));
- }
-
- private static Stream provideTestCasesForLongestPalindrome() {
- return Stream.of(Arguments.of("babad", "bab"), Arguments.of("cbbd", "bb"), Arguments.of("a", "a"), Arguments.of("", ""), Arguments.of("abc", "a"), Arguments.of(null, ""), Arguments.of("aaaaa", "aaaaa"));
- }
-}
diff --git a/src/test/java/com/thealgorithms/strings/RabinKarpTest.java b/src/test/java/com/thealgorithms/strings/RabinKarpTest.java
new file mode 100644
index 000000000000..6dfd099e9bca
--- /dev/null
+++ b/src/test/java/com/thealgorithms/strings/RabinKarpTest.java
@@ -0,0 +1,46 @@
+package com.thealgorithms.strings;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class RabinKarpTest {
+
+ @Test
+ public void testNullInputs() {
+ assertEquals(List.of(), RabinKarp.search(null, "A"));
+ assertEquals(List.of(), RabinKarp.search("A", null));
+ assertEquals(List.of(), RabinKarp.search(null, null));
+ }
+
+ @Test
+ public void testHashCollision() {
+ // 'a' = 97. (char)198 % 101 = 97.
+ // For length 1, h = 1. p = 97. t = 198 % 101 = 97.
+ // Collision occurs, loop checks characters: 198 != 97, breaks.
+ char collisionChar = (char) 198;
+ String text = String.valueOf(collisionChar);
+ String pattern = "a";
+ assertEquals(List.of(), RabinKarp.search(text, pattern));
+ }
+
+ @Test
+ public void testSearchWithCustomQ() {
+ // Using a different prime
+ assertEquals(List.of(0, 1), RabinKarp.search("AAAA", "AAA", 13));
+ }
+
+ @Test
+ public void testRabinKarpSearch() {
+ assertEquals(List.of(0, 1), RabinKarp.search("AAAAABAAABA", "AAAA"));
+ assertEquals(List.of(0, 3), RabinKarp.search("ABCABC", "ABC"));
+ assertEquals(List.of(10), RabinKarp.search("ABABDABACDABABCABAB", "ABABCABAB"));
+ assertEquals(List.of(), RabinKarp.search("ABCDE", "FGH"));
+ assertEquals(List.of(), RabinKarp.search("A", "AA"));
+ assertEquals(List.of(0, 1, 2), RabinKarp.search("AAA", "A"));
+ assertEquals(List.of(0), RabinKarp.search("A", "A"));
+ assertEquals(List.of(), RabinKarp.search("", "A"));
+ assertEquals(List.of(), RabinKarp.search("A", ""));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java b/src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java
deleted file mode 100644
index 411b11e743b8..000000000000
--- a/src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.thealgorithms.strings;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.CsvSource;
-
-public class ValidParenthesesTest {
-
- @ParameterizedTest(name = "Input: \"{0}\" β Expected: {1}")
- @CsvSource({"'()', true", "'()[]{}', true", "'(]', false", "'{[]}', true", "'([{}])', true", "'([)]', false", "'', true", "'(', false", "')', false", "'{{{{}}}}', true", "'[({})]', true", "'[(])', false", "'[', false", "']', false", "'()()()()', true", "'(()', false", "'())', false",
- "'{[()()]()}', true"})
- void
- testIsValid(String input, boolean expected) {
- assertEquals(expected, ValidParentheses.isValid(input));
- }
-
- @Test
- void testNullInputThrows() {
- IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> ValidParentheses.isValid(null));
- assertEquals("Input string cannot be null", ex.getMessage());
- }
-
- @ParameterizedTest(name = "Input: \"{0}\" β throws IllegalArgumentException")
- @CsvSource({"'a'", "'()a'", "'[123]'", "'{hello}'", "'( )'", "'\t'", "'\n'", "'@#$%'"})
- void testInvalidCharactersThrow(String input) {
- IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> ValidParentheses.isValid(input));
- assertTrue(ex.getMessage().startsWith("Unexpected character"));
- }
-}
diff --git a/src/test/java/com/thealgorithms/strings/WordLadderTest.java b/src/test/java/com/thealgorithms/strings/WordLadderTest.java
index 221953411da7..c029940abfb0 100644
--- a/src/test/java/com/thealgorithms/strings/WordLadderTest.java
+++ b/src/test/java/com/thealgorithms/strings/WordLadderTest.java
@@ -24,7 +24,7 @@ public class WordLadderTest {
public void testWordLadder() {
List wordList1 = Arrays.asList("hot", "dot", "dog", "lot", "log", "cog");
- assertEquals(WordLadder.ladderLength("hit", "cog", wordList1), 5);
+ assertEquals(5, WordLadder.ladderLength("hit", "cog", wordList1));
}
/**
@@ -39,7 +39,7 @@ public void testWordLadder() {
public void testWordLadder2() {
List wordList2 = Arrays.asList("hot", "dot", "dog", "lot", "log");
- assertEquals(WordLadder.ladderLength("hit", "cog", wordList2), 0);
+ assertEquals(0, WordLadder.ladderLength("hit", "cog", wordList2));
}
/**
@@ -54,7 +54,7 @@ public void testWordLadder2() {
public void testWordLadder3() {
List wordList3 = emptyList();
- assertEquals(WordLadder.ladderLength("hit", "cog", wordList3), 0);
+ assertEquals(0, WordLadder.ladderLength("hit", "cog", wordList3));
}
@ParameterizedTest
diff --git a/src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java b/src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java
index 2cbbfe3d2dd8..9bf118c9b844 100644
--- a/src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java
+++ b/src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java
@@ -9,8 +9,8 @@ public class ZigZagPatternTest {
public void testZigZagPattern() {
String input1 = "HelloWorldFromJava";
String input2 = "javaIsAProgrammingLanguage";
- Assertions.assertEquals(ZigZagPattern.encode(input1, 4), "HooeWrrmalolFJvlda");
- Assertions.assertEquals(ZigZagPattern.encode(input2, 4), "jAaLgasPrmgaaevIrgmnnuaoig");
+ Assertions.assertEquals("HooeWrrmalolFJvlda", ZigZagPattern.encode(input1, 4));
+ Assertions.assertEquals("jAaLgasPrmgaaevIrgmnnuaoig", ZigZagPattern.encode(input2, 4));
// Edge cases
Assertions.assertEquals("ABC", ZigZagPattern.encode("ABC", 1)); // Single row
Assertions.assertEquals("A", ZigZagPattern.encode("A", 2)); // numRows > length of string