From 8ba295b1adb6c0d8f8e14731563e5521ea8469ee Mon Sep 17 00:00:00 2001
From: Nishanth Chandra <104753233+ThisIsNishanth@users.noreply.github.com>
Date: Mon, 12 Dec 2022 00:43:27 +0530
Subject: [PATCH 0001/1088] Added Order Agnostic Binary Search problem in
Searches folder. (#3791)
* Added Order Agnostic Binary Search problem
* Update OrderAgnosticBinSearch.java
* Added JUnit Tests and removed redundant code.
* Made minor changes in JUnit Tests
* Removed tests for main folder and added docs.
* Added OrderAgnosticBinarySearchTest.java
* Renamed file to avoid errors.
* Updated the file to avoid build error
---
.../searches/OrderAgnosticBinarySearch.java | 47 ++++++++++++
.../OrderAgnosticBinarySearchTest.java | 72 +++++++++++++++++++
2 files changed, 119 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/searches/OrderAgnosticBinarySearch.java
create mode 100644 src/test/java/com/thealgorithms/searches/OrderAgnosticBinarySearchTest.java
diff --git a/src/main/java/com/thealgorithms/searches/OrderAgnosticBinarySearch.java b/src/main/java/com/thealgorithms/searches/OrderAgnosticBinarySearch.java
new file mode 100644
index 000000000000..39f26a97dd31
--- /dev/null
+++ b/src/main/java/com/thealgorithms/searches/OrderAgnosticBinarySearch.java
@@ -0,0 +1,47 @@
+package com.thealgorithms.searches;
+
+//URL: https://www.geeksforgeeks.org/order-agnostic-binary-search/
+
+/* Order Agnostic Binary Search is an algorithm where we do not know whether the given
+ sorted array is ascending or descending order.
+ We declare a boolean variable to find whether the array is ascending order.
+ In the while loop, we use the two pointer method (start and end) to get the middle element.
+ if the middle element is equal to our target element, then that is the answer.
+ If not, then we check if the array is ascending or descending order.
+ Depending upon the condition, respective statements will be executed and we will get our answer.
+ */
+
+ public class OrderAgnosticBinarySearch {
+
+ static int BinSearchAlgo(int arr[], int start, int end, int target) {
+
+ // Checking whether the given array is ascending order
+ boolean AscOrd = arr[start] < arr[end];
+
+ while (start <= end) {
+ int middle = start + (end - start) / 2;
+
+ // Check if the desired element is present at the middle position
+ if (arr[middle] == target)
+ return middle; // returns the index of the middle element
+
+ // Ascending order
+ if (AscOrd) {
+ if (arr[middle] < target)
+ start = middle + 1;
+ else
+ end = middle - 1;
+ }
+
+ // Descending order
+ else {
+ if (arr[middle] > target)
+ start = middle + 1;
+ else
+ end = middle - 1;
+ }
+ }
+ // Element is not present
+ return -1;
+ }
+ }
diff --git a/src/test/java/com/thealgorithms/searches/OrderAgnosticBinarySearchTest.java b/src/test/java/com/thealgorithms/searches/OrderAgnosticBinarySearchTest.java
new file mode 100644
index 000000000000..8194d345d1cb
--- /dev/null
+++ b/src/test/java/com/thealgorithms/searches/OrderAgnosticBinarySearchTest.java
@@ -0,0 +1,72 @@
+package com.thealgorithms.searches;
+
+import com.thealgorithms.searches.OrderAgnosticBinarySearch;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+
+public class OrderAgnosticBinarySearchTest {
+ @Test
+ //valid Test Case
+ public void ElementInMiddle() {
+ int[] arr = {10, 20, 30, 40, 50};
+ int answer = OrderAgnosticBinarySearch.BinSearchAlgo(arr, 0, arr.length - 1, 30);
+ System.out.println(answer);
+ int expected = 2;
+ assertEquals(expected, answer);
+ }
+
+ @Test
+ //valid Test Case
+ public void RightHalfDescOrder() {
+ int[] arr = {50, 40, 30, 20, 10};
+ int answer = OrderAgnosticBinarySearch.BinSearchAlgo(arr, 0, arr.length - 1, 10);
+ System.out.println(answer);
+ int expected = 4;
+ assertEquals(expected, answer);
+ }
+
+ @Test
+ //valid test case
+ public void LeftHalfDescOrder() {
+ int[] arr = {50, 40, 30, 20, 10};
+ int answer = OrderAgnosticBinarySearch.BinSearchAlgo(arr, 0, arr.length - 1, 50);
+ System.out.println(answer);
+ int expected = 0;
+ assertEquals(expected, answer);
+ }
+
+ @Test
+ //valid test case
+ public void RightHalfAscOrder() {
+ int[] arr = {10, 20, 30, 40, 50};
+ int answer = OrderAgnosticBinarySearch.BinSearchAlgo(arr, 0, arr.length - 1, 50);
+ System.out.println(answer);
+ int expected = 4;
+ assertEquals(expected, answer);
+ }
+
+ @Test
+ //valid test case
+ public void LeftHalfAscOrder() {
+ int[] arr = {10, 20, 30, 40, 50};
+ int answer = OrderAgnosticBinarySearch.BinSearchAlgo(arr, 0, arr.length - 1, 10);
+ System.out.println(answer);
+ int expected = 0;
+ assertEquals(expected, answer);
+ }
+
+ @Test
+ //valid test case
+ public void ElementNotFound() {
+ int[] arr = {10, 20, 30, 40, 50};
+ int answer = OrderAgnosticBinarySearch.BinSearchAlgo(arr, 0, arr.length - 1, 100);
+ System.out.println(answer);
+ int expected = -1;
+ assertEquals(expected, answer);
+ }
+ }
From 5512fea0a8331b71fb90f15d98cc6f85df7d2a02 Mon Sep 17 00:00:00 2001
From: PuneetTri <43619937+PuneetTri@users.noreply.github.com>
Date: Tue, 13 Dec 2022 23:32:15 +0530
Subject: [PATCH 0002/1088] Improve priority queues with max-heap (#3648)
---
.../datastructures/queues/PriorityQueues.java | 130 ++++++++++++------
1 file changed, 90 insertions(+), 40 deletions(-)
diff --git a/src/main/java/com/thealgorithms/datastructures/queues/PriorityQueues.java b/src/main/java/com/thealgorithms/datastructures/queues/PriorityQueues.java
index d44fa30f9b6a..21432a53ce5c 100644
--- a/src/main/java/com/thealgorithms/datastructures/queues/PriorityQueues.java
+++ b/src/main/java/com/thealgorithms/datastructures/queues/PriorityQueues.java
@@ -1,5 +1,8 @@
package com.thealgorithms.datastructures.queues;
+
+
+
/**
* This class implements a PriorityQueue.
*
@@ -8,6 +11,8 @@
* most important elements are placed at the front/on the top. In this example I
* give numbers that are bigger, a higher priority. Queues in theory have no
* fixed size but when using an array implementation it does.
+ *
+ * Additional contibutions made by: PuneetTri(https://github.com/PuneetTri)
*/
class PriorityQueue {
@@ -25,42 +30,113 @@ class PriorityQueue {
private int nItems;
/**
- * Constructor
+ * Default Constructor
+ */
+
+ public PriorityQueue() {
+ /* If capacity is not defined, default size of 11 would be used
+ * capacity=max+1 because we cant access 0th element of PQ, and to
+ * accomodate (max)th elements we need capacity to be max+1.
+ * Parent is at position k, child at position (k*2,k*2+1), if we
+ * use position 0 in our queue, its child would be at:
+ * (0*2, 0*2+1) -> (0,0). This is why we start at position 1
+ */
+ int size = 11; // Default value of 11
+ maxSize = size + 1;
+ queueArray = new int[maxSize];
+ nItems = 0;
+ }
+
+ /**
+ * Parameterized Constructor
*
* @param size Size of the queue
*/
+
public PriorityQueue(int size) {
- maxSize = size;
- queueArray = new int[size];
+ maxSize = size + 1;
+ queueArray = new int[maxSize];
nItems = 0;
}
+ /**
+ * Helper function for the max-heap implementation of PQ
+ * Function would help demote parent node to their correct
+ * position
+ *
+ * @param pos Position of newly added element at bottom
+ */
+ private void swim(int pos) {
+ // Check if parent is smaller than child node
+ while (pos > 1 && (queueArray[pos / 2] < queueArray[pos])) {
+ // In such case swap value of child with parent
+ int temp = queueArray[pos];
+ queueArray[pos] = queueArray[pos / 2];
+ queueArray[pos / 2] = temp;
+ pos = pos / 2; // Jump to position of parent node
+ }
+ // Promotion of child node will go on until it becomes smaller than the parent
+ }
+
+ /**
+ * Helper function for the max-heap implementation of PQ
+ * Function would help demote parent node to their correct
+ * position
+ *
+ * @param pos Position of element at top
+ */
+ private void sink(int pos) {
+ // Check if node's position is that of parent node
+ while (2 * pos <= nItems) {
+ int current = 2 * pos; // Jump to the positon of child node
+ // Compare both the children for the greater one
+ if (current < nItems && queueArray[current] < queueArray[current + 1]) current++;
+ // If the parent node is greater, sink operation is complete. Break the loop
+ if (queueArray[pos] >= queueArray[current]) break;
+
+ // If not exchange the value of parent with child
+ int temp = queueArray[pos];
+ queueArray[pos] = queueArray[current];
+ queueArray[current] = temp;
+ pos = current; // Exchange parent position to child position in the array
+ }
+ }
+
/**
* Inserts an element in it's appropriate place
*
* @param value Value to be inserted
*/
public void insert(int value) {
+ // Print overflow message if the capacity is full
if (isFull()) {
throw new RuntimeException("Queue is full");
} else {
- int j = nItems - 1; // index of last element
- while (j >= 0 && queueArray[j] > value) {
- queueArray[j + 1] = queueArray[j]; // Shifts every element up to make room for insertion
- j--;
- }
- queueArray[j + 1] = value; // Once the correct position is found the value is inserted
- nItems++;
+ queueArray[++nItems] = value;
+ swim(nItems); // Swim up the element to its correct position
}
}
/**
- * Remove the element from the front of the queue
+ * Dequeue the element with the max priority from PQ
*
* @return The element removed
*/
public int remove() {
- return queueArray[--nItems];
+ if (isEmpty()) {
+ throw new RuntimeException("Queue is Empty");
+ } else {
+ int max = queueArray[1]; // By defintion of our max-heap, value at queueArray[1] pos is the greatest
+
+ // Swap max and last element
+ int temp = queueArray[1];
+ queueArray[1] = queueArray[nItems];
+ queueArray[nItems] = temp;
+ queueArray[nItems--] = 0; // Nullify the last element from the priority queue
+ sink(1); // Sink the element in order
+
+ return max;
+ }
}
/**
@@ -69,7 +145,7 @@ public int remove() {
* @return element at the front of the queue
*/
public int peek() {
- return queueArray[nItems - 1];
+ return queueArray[1];
}
/**
@@ -87,7 +163,7 @@ public boolean isEmpty() {
* @return true if the queue is full
*/
public boolean isFull() {
- return (nItems == maxSize);
+ return (nItems == maxSize - 1);
}
/**
@@ -100,29 +176,3 @@ public int getSize() {
}
}
-/**
- * This class implements the PriorityQueue class above.
- *
- * @author Unknown
- */
-public class PriorityQueues {
-
- /**
- * Main method
- *
- * @param args Command Line Arguments
- */
- public static void main(String[] args) {
- PriorityQueue myQueue = new PriorityQueue(4);
- myQueue.insert(10);
- myQueue.insert(2);
- myQueue.insert(5);
- myQueue.insert(3);
- // [2, 3, 5, 10] Here higher numbers have higher priority, so they are on the top
-
- for (int i = 3; i >= 0; i--) {
- System.out.print(myQueue.remove() + " "); // will print the queue in reverse order [10, 5, 3, 2]
- }
- // As you can see, a Priority Queue can be used as a sorting algotithm
- }
-}
From 7fe9928ee8478736b5b5dc8f5d353f70b96ff56d Mon Sep 17 00:00:00 2001
From: David Leal
Date: Sat, 17 Dec 2022 07:28:52 -0600
Subject: [PATCH 0003/1088] docs: improve the issue forms (#3797)
* docs: improve the issue forms
* Update directory
Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
---
.github/ISSUE_TEMPLATE/bug_report.yml | 6 +++---
.github/ISSUE_TEMPLATE/config.yml | 6 +++++-
.github/ISSUE_TEMPLATE/feature_request.yml | 10 ++++------
.github/ISSUE_TEMPLATE/{other_issue.yml => other.yml} | 5 +----
DIRECTORY.md | 9 +++++++++
5 files changed, 22 insertions(+), 14 deletions(-)
rename .github/ISSUE_TEMPLATE/{other_issue.yml => other.yml} (86%)
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 69048ba21d31..8262d0359790 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,6 +1,6 @@
name: "Bug report"
description: "Create a report to help us improve"
-title: "[BUG]"
+title: "[BUG] ""
labels: ["bug"]
body:
- type: textarea
@@ -40,6 +40,6 @@ body:
id: context
attributes:
label: "Additional context"
- description: "Add any other context about the problem here."
+ description: "Is there anything else we should know about this bug report?"
validations:
- required: false
\ No newline at end of file
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index ec4bb386bcf8..875cc4efab00 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1 +1,5 @@
-blank_issues_enabled: false
\ No newline at end of file
+blank_issues_enabled: false
+contact_links:
+ - name: Discord community
+ url: https://the-algorithms.com/discord/
+ about: Have any questions or found any bugs? Please contact us via Discord
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index 26bbee2a674a..98ff394158be 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -1,7 +1,7 @@
name: "Feature Request"
description: "Suggest an idea for this project"
-title: "[FEATURE REQUEST]"
-labels: ["feature_request"]
+title: "[FEATURE REQUEST] "
+labels: ["enhancement"]
body:
- type: textarea
id: description
@@ -13,13 +13,11 @@ body:
- type: markdown
attributes:
value: |
- "
For new implementations, please specify the name and problem statement for the algorithm.
For algorithm enhancements, specify what needs to be changed and why. For example:
- Adding tests.
- Optimizing logic.
- Refactoring the file and folders for better structure.
- "
- type: textarea
id: needdetails
attributes:
@@ -31,6 +29,6 @@ body:
id: extrainfo
attributes:
label: "Additional Information"
- description: "Add any other Information or Screenshot about the request here."
+ description: "Add any other information or screenshots about the request here."
validations:
- required: false
\ No newline at end of file
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/other_issue.yml b/.github/ISSUE_TEMPLATE/other.yml
similarity index 86%
rename from .github/ISSUE_TEMPLATE/other_issue.yml
rename to .github/ISSUE_TEMPLATE/other.yml
index de8686fd740a..bf8b29f481c8 100644
--- a/.github/ISSUE_TEMPLATE/other_issue.yml
+++ b/.github/ISSUE_TEMPLATE/other.yml
@@ -3,9 +3,6 @@ description: Use this for any other issues. Do NOT create blank issues
title: "[OTHER]"
labels: ["awaiting triage"]
body:
- - type: markdown
- attributes:
- value: "# Other issue"
- type: textarea
id: issuedescription
attributes:
@@ -19,4 +16,4 @@ body:
label: Additional information
description: Is there anything else we should know about this issue?
validations:
- required: false
\ No newline at end of file
+ required: false
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 983c6b4814c5..d4dc56ebb7df 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -409,6 +409,7 @@
* [LinearSearchThread](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/searches/LinearSearchThread.java)
* [LowerBound](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/searches/LowerBound.java)
* [MonteCarloTreeSearch](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/searches/MonteCarloTreeSearch.java)
+ * [OrderAgnosticBinarySearch](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/searches/OrderAgnosticBinarySearch.java)
* [PerfectBinarySearch](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java)
* [QuickSelect](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/searches/QuickSelect.java)
* [RabinKarpAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/searches/RabinKarpAlgorithm.java)
@@ -533,6 +534,8 @@
* [FibonacciHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/FibonacciHeapTest.java)
* lists
* [SkipListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/SkipListTest.java)
+ * queues
+ * [PriorityQueuesTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/PriorityQueuesTest.java)
* trees
* [CeilInBinarySearchTreeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/CeilInBinarySearchTreeTest.java)
* [CheckTreeIsSymmetricTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/CheckTreeIsSymmetricTest.java)
@@ -626,6 +629,7 @@
* [BreadthFirstSearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/BreadthFirstSearchTest.java)
* [HowManyTimesRotatedTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/HowManyTimesRotatedTest.java)
* [KMPSearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/KMPSearchTest.java)
+ * [OrderAgnosticBinarySearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/OrderAgnosticBinarySearchTest.java)
* [QuickSelectTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/QuickSelectTest.java)
* [RabinKarpAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/RabinKarpAlgorithmTest.java)
* [RowColumnWiseSorted2dArrayBinarySearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/RowColumnWiseSorted2dArrayBinarySearchTest.java)
@@ -634,7 +638,9 @@
* [BinaryInsertionSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/BinaryInsertionSortTest.java)
* [BogoSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/BogoSortTest.java)
* [BubbleSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/BubbleSortTest.java)
+ * [BucketSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/BucketSortTest.java)
* [CocktailShakerSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CocktailShakerSortTest.java)
+ * [CombSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CombSortTest.java)
* [DualPivotQuickSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DualPivotQuickSortTest.java)
* [DutchNationalFlagSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DutchNationalFlagSortTest.java)
* [HeapSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/HeapSortTest.java)
@@ -644,10 +650,13 @@
* [OddEvenSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/OddEvenSortTest.java)
* [QuickSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/QuickSortTest.java)
* [SelectionSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/SelectionSortTest.java)
+ * [ShellSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/ShellSortTest.java)
+ * [SimpleSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/SimpleSortTest.java)
* [SlowSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/SlowSortTest.java)
* [SortUtilsRandomGeneratorTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/SortUtilsRandomGeneratorTest.java)
* [SortUtilsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/SortUtilsTest.java)
* [StrandSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/StrandSortTest.java)
+ * [TimSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/TimSortTest.java)
* [TopologicalSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/TopologicalSortTest.java)
* [WiggleSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/WiggleSortTest.java)
* strings
From fb09eb289e63ea8932a3b28418e8ef9888ae5837 Mon Sep 17 00:00:00 2001
From: David Leal
Date: Sat, 17 Dec 2022 19:35:47 -0600
Subject: [PATCH 0004/1088] fix: bug report form error
---
.github/ISSUE_TEMPLATE/bug_report.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 8262d0359790..9c906c381608 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,6 +1,6 @@
name: "Bug report"
description: "Create a report to help us improve"
-title: "[BUG] ""
+title: "[BUG] "
labels: ["bug"]
body:
- type: textarea
From c6694fc1bdcaa04d1af6a3aba3b20e082b92ef95 Mon Sep 17 00:00:00 2001
From: Nathan Cheshire <60986919+NathanCheshire@users.noreply.github.com>
Date: Sat, 17 Dec 2022 21:03:09 -0600
Subject: [PATCH 0005/1088] Simplifying boolean returns (#3796)
* Simplifying boolean returns
* add comment back
---
.../com/thealgorithms/maths/DudeneyNumber.java | 6 +-----
.../com/thealgorithms/sorts/LinkListSort.java | 18 +++---------------
.../com/thealgorithms/strings/Anagrams.java | 7 ++-----
3 files changed, 6 insertions(+), 25 deletions(-)
diff --git a/src/main/java/com/thealgorithms/maths/DudeneyNumber.java b/src/main/java/com/thealgorithms/maths/DudeneyNumber.java
index 11fe03d8474a..ab9fb70b1cf0 100644
--- a/src/main/java/com/thealgorithms/maths/DudeneyNumber.java
+++ b/src/main/java/com/thealgorithms/maths/DudeneyNumber.java
@@ -33,10 +33,6 @@ public static boolean isDudeney(int n) {
}
//If the cube root of the number is not equal to the sum of its digits we return false.
- if (cube_root != sum_of_digits) {
- return false;
- }
-
- return true;
+ return cube_root == sum_of_digits;
}
}
diff --git a/src/main/java/com/thealgorithms/sorts/LinkListSort.java b/src/main/java/com/thealgorithms/sorts/LinkListSort.java
index ed0e1db1bdcc..3c9ba1b7d17d 100644
--- a/src/main/java/com/thealgorithms/sorts/LinkListSort.java
+++ b/src/main/java/com/thealgorithms/sorts/LinkListSort.java
@@ -44,11 +44,7 @@ public static boolean isSorted(int p[], int option) {
Arrays.sort(b);
// array b is sorted and it will return true when checked with sorted list
LinkListSort uu = new LinkListSort();
- if (uu.compare(a, b)) {
- return true;
- } else {
- return false;
- }
+ return uu.compare(a, b);
// The given array and the expected array is checked if both are same then true
// is displayed else false is displayed
case 2:
@@ -73,11 +69,7 @@ public static boolean isSorted(int p[], int option) {
}
LinkListSort uu1 = new LinkListSort();
// array b is not sorted and it will return false when checked with sorted list
- if (uu1.compare(a, b)) {
- return true;
- } else {
- return false;
- }
+ return uu1.compare(a, b);
// The given array and the expected array is checked if both are same then true
// is displayed else false is displayed
case 3:
@@ -103,11 +95,7 @@ public static boolean isSorted(int p[], int option) {
Arrays.sort(b);
// array b is sorted and it will return true when checked with sorted list
LinkListSort uu2 = new LinkListSort();
- if (uu2.compare(a, b)) {
- return true;
- } else {
- return false;
- }
+ return uu2.compare(a, b);
// The given array and the expected array is checked if both are same then true
// is displayed else false is displayed
default:
diff --git a/src/main/java/com/thealgorithms/strings/Anagrams.java b/src/main/java/com/thealgorithms/strings/Anagrams.java
index 1d61e42e5852..dcde8647f78d 100644
--- a/src/main/java/com/thealgorithms/strings/Anagrams.java
+++ b/src/main/java/com/thealgorithms/strings/Anagrams.java
@@ -56,11 +56,8 @@ boolean approach1(String s, String t) {
Arrays.sort(
d
);/* In this approach the strings are stored in the character arrays and both the arrays are sorted. After that both the arrays are compared for checking anangram */
- if (Arrays.equals(c, d)) {
- return true;
- } else {
- return false;
- }
+
+ return Arrays.equals(c, d);
}
}
From 6a0035d87233ec4369bbdf12bf05003fee12ab84 Mon Sep 17 00:00:00 2001
From: Tanmay Jadhav <55030410+TanmayJadhav@users.noreply.github.com>
Date: Wed, 28 Dec 2022 17:31:05 +0530
Subject: [PATCH 0006/1088] Add description for SkipList.java (#3503)
---
src/main/java/com/thealgorithms/datastructures/lists/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/README.md b/src/main/java/com/thealgorithms/datastructures/lists/README.md
index b86db4b346e3..cfb8221abca6 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/README.md
+++ b/src/main/java/com/thealgorithms/datastructures/lists/README.md
@@ -29,3 +29,4 @@ The `next` variable points to the next node in the data structure and value stor
5. `DoublyLinkedList.java` : A modification of singly linked list which has a `prev` pointer to point to the previous node.
6. `Merge_K_SortedLinkedlist.java` : Merges K sorted linked list with mergesort (mergesort is also the most efficient sorting algorithm for linked list).
7. `RandomNode.java` : Selects a random node from given linked list and diplays it.
+8. `SkipList.java` : Data Structure used for storing a sorted list of elements with help of a Linked list hierarchy that connects to subsequences of elements.
From 91234747294a788a8f7cd6a918f24e7df74832f2 Mon Sep 17 00:00:00 2001
From: adrianparas <97486758+adrianparas@users.noreply.github.com>
Date: Thu, 29 Dec 2022 07:19:35 -0500
Subject: [PATCH 0007/1088] Add Leftist Heap (#3789)
Co-authored-by: Adrian Paras
---
.../datastructures/heaps/LeftistHeap.java | 118 ++++++++++++++++++
.../datastructures/heaps/LeftistHeapTest.java | 28 +++++
2 files changed, 146 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java b/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java
new file mode 100644
index 000000000000..66861ac1d111
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java
@@ -0,0 +1,118 @@
+package com.thealgorithms.datastructures.heaps;
+
+import java.util.ArrayList;
+
+/*
+ * This is a leftist heap that follows the same operations as a
+ * binary min heap, but may be unbalanced at times and follows a
+ * leftist property, in which the left side is more heavy on the
+ * right based on the null-path length (npl) values.
+ *
+ * Source: https://iq.opengenus.org/leftist-heap/
+ *
+ */
+
+public class LeftistHeap {
+ private class Node {
+ private int element, npl;
+ private Node left, right;
+
+ // Node constructor setting the data element and left/right pointers to null
+ private Node(int element) {
+ this.element = element;
+ left = right = null;
+ npl = 0;
+ }
+ }
+
+ private Node root;
+
+ // Constructor
+ public LeftistHeap() {
+ root = null;
+ }
+
+ // Checks if heap is empty
+ public boolean isEmpty() {
+ return root == null;
+ }
+
+ // Resets structure to initial state
+ public void clear() {
+ // We will put head is null
+ root = null;
+ }
+
+ // Merge function that merges the contents of another leftist heap with the
+ // current one
+ public void merge(LeftistHeap h1) {
+ // If the present function is rhs then we ignore the merge
+ root = merge(root, h1.root);
+ h1.root = null;
+ }
+
+ // Function merge with two Nodes a and b
+ public Node merge(Node a, Node b) {
+ if (a == null)
+ return b;
+
+ if (b == null)
+ return a;
+
+ // Violates leftist property, so must do a swap
+ if (a.element > b.element) {
+ Node temp = a;
+ a = b;
+ b = temp;
+ }
+
+ // Now we call the function merge to merge a and b
+ a.right = merge(a.right, b);
+
+ // Violates leftist property so must swap here
+ if (a.left == null) {
+ a.left = a.right;
+ a.right = null;
+ } else {
+ if (a.left.npl < a.right.npl) {
+ Node temp = a.left;
+ a.left = a.right;
+ a.right = temp;
+ }
+ a.npl = a.right.npl + 1;
+ }
+ return a;
+ }
+
+ // Function insert. Uses the merge function to add the data
+ public void insert(int a) {
+ root = merge(new Node(a), root);
+ }
+
+ // Returns and removes the minimum element in the heap
+ public int extract_min() {
+ // If is empty return -1
+ if (isEmpty())
+ return -1;
+
+ int min = root.element;
+ root = merge(root.left, root.right);
+ return min;
+ }
+
+ // Function returning a list of an in order traversal of the data structure
+ public ArrayList in_order() {
+ ArrayList lst = new ArrayList<>();
+ in_order_aux(root, lst);
+ return new ArrayList<>(lst);
+ }
+
+ // Auxiliary function for in_order
+ private void in_order_aux(Node n, ArrayList lst) {
+ if (n == null)
+ return;
+ in_order_aux(n.left, lst);
+ lst.add(n.element);
+ in_order_aux(n.right, lst);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java b/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java
new file mode 100644
index 000000000000..b0cb0d19674b
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java
@@ -0,0 +1,28 @@
+package com.thealgorithms.datastructures.heaps;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class LeftistHeapTest {
+
+ @Test
+ void testLeftistHeap() {
+ LeftistHeap heap = new LeftistHeap();
+ Assertions.assertTrue(heap.isEmpty());
+ heap.insert(6);
+ Assertions.assertTrue(!heap.isEmpty());
+ heap.insert(2);
+ heap.insert(3);
+ heap.insert(1);
+ heap.in_order();
+ Assertions.assertTrue(heap.in_order().toString().equals("[6, 2, 3, 1]"));
+ Assertions.assertTrue(heap.extract_min() == 1);
+ Assertions.assertTrue(heap.in_order().toString().equals("[6, 2, 3]"));
+ heap.insert(8);
+ heap.insert(12);
+ heap.insert(4);
+ Assertions.assertTrue(heap.in_order().toString().equals("[8, 3, 12, 2, 6, 4]"));
+ heap.clear();
+ Assertions.assertTrue(heap.isEmpty());
+ }
+}
\ No newline at end of file
From ce55420418e991acf96c391dabb73d8ffb1e30cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EC=A4=80=ED=99=8D?=
Date: Sun, 1 Jan 2023 04:09:09 +0900
Subject: [PATCH 0008/1088] Add tests for Tree Sort (#3787)
---
.../com/thealgorithms/sorts/TreeSortTest.java | 88 +++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 src/test/java/com/thealgorithms/sorts/TreeSortTest.java
diff --git a/src/test/java/com/thealgorithms/sorts/TreeSortTest.java b/src/test/java/com/thealgorithms/sorts/TreeSortTest.java
new file mode 100644
index 000000000000..5c99c2d691d0
--- /dev/null
+++ b/src/test/java/com/thealgorithms/sorts/TreeSortTest.java
@@ -0,0 +1,88 @@
+package com.thealgorithms.sorts;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author Tabbygray (https://github.com/Tabbygray)
+ * @see TreeSort
+ */
+
+public class TreeSortTest {
+ private TreeSort treeSort = new TreeSort();
+
+ @Test
+ public void treeSortEmptyArray(){
+ Integer[] inputArray = {};
+ Integer[] outputArray = treeSort.sort(inputArray);
+ Integer[] expectedOutput = {};
+ assertArrayEquals(outputArray, expectedOutput);
+ }
+
+ @Test
+ public void treeSortSingleStringElement() {
+ String[] inputArray = {"Test"};
+ String[] outputArray = treeSort.sort(inputArray);
+ String[] expectedArray = {"Test"};
+ assertArrayEquals(outputArray, expectedArray);
+ }
+
+ @Test
+ public void treeSortStringArray() {
+ String[] inputArray = {
+ "F6w9",
+ "l1qz",
+ "dIxH",
+ "larj",
+ "kRzy",
+ "vnNH",
+ "3ftM",
+ "hc4n",
+ "C5Qi",
+ "btGF"
+ };
+ String[] outputArray = treeSort.sort(inputArray);
+ String[] expectedArray = {
+ "3ftM",
+ "C5Qi",
+ "F6w9",
+ "btGF",
+ "dIxH",
+ "hc4n",
+ "kRzy",
+ "l1qz",
+ "larj",
+ "vnNH"
+ };
+ assertArrayEquals(outputArray, expectedArray);
+ }
+
+ @Test
+ public void treeSortIntegerArray() {
+ Integer[] inputArray = { -97, -44, -4, -85, -92, 74, 79, -26, 76, -5 };
+ Integer[] outputArray = treeSort.sort(inputArray);
+ Integer[] expectedArray = { -97, -92, -85, -44, -26, -5, -4, 74, 76, 79 };
+ assertArrayEquals(outputArray, expectedArray);
+ }
+
+ @Test
+ public void treeSortDoubleArray() {
+ Double[] inputArray = {
+ 0.8047485045, 0.4493112337,
+ 0.8298433723, 0.2691406748,
+ 0.2482782839, 0.5976243420,
+ 0.6746235284, 0.0552623569,
+ 0.3515624123, 0.0536747336
+ };
+ Double[] outputArray = treeSort.sort(inputArray);
+ Double[] expectedArray = {
+ 0.0536747336, 0.0552623569,
+ 0.2482782839, 0.2691406748,
+ 0.3515624123, 0.4493112337,
+ 0.5976243420, 0.6746235284,
+ 0.8047485045, 0.8298433723
+ };
+ assertArrayEquals(outputArray, expectedArray);
+ }
+}
From 1eedaeb07387c521f02ab211f0664e500dbb2ba9 Mon Sep 17 00:00:00 2001
From: Narek Karapetian
Date: Sun, 1 Jan 2023 06:50:56 -0800
Subject: [PATCH 0009/1088] Move common tests for sorting algorithms to the
base test class (#3782)
* bug fix for CircularBuffer + refactoring + add unit tests
* change Insertion sort to classical implementation + add isSorted function to SortUtils + add SortUtilsRandomGenerator for generating random values and arrays
* little fix
* move all common tests to SortingAlgorithmTest and utilize them
Co-authored-by: Debasish Biswas
---
.../com/thealgorithms/sorts/SortUtils.java | 7 +
.../com/thealgorithms/sorts/HeapSortTest.java | 95 +---------
.../thealgorithms/sorts/MergeSortTest.java | 95 +---------
.../thealgorithms/sorts/QuickSortTest.java | 58 +-----
.../thealgorithms/sorts/SortUtilsTest.java | 30 ++-
.../sorts/SortingAlgorithmTest.java | 171 ++++++++++++++++++
.../com/thealgorithms/sorts/TimSortTest.java | 90 +--------
7 files changed, 222 insertions(+), 324 deletions(-)
create mode 100644 src/test/java/com/thealgorithms/sorts/SortingAlgorithmTest.java
diff --git a/src/main/java/com/thealgorithms/sorts/SortUtils.java b/src/main/java/com/thealgorithms/sorts/SortUtils.java
index 83b94c9a922f..f9f99055a49e 100644
--- a/src/main/java/com/thealgorithms/sorts/SortUtils.java
+++ b/src/main/java/com/thealgorithms/sorts/SortUtils.java
@@ -112,4 +112,11 @@ static > boolean isSorted(T[] array) {
return false;
return true;
}
+
+ static > boolean isSorted(List list) {
+ for (int i = 1; i < list.size(); i++)
+ if (less(list.get(i), list.get(i - 1)))
+ return false;
+ return true;
+ }
}
diff --git a/src/test/java/com/thealgorithms/sorts/HeapSortTest.java b/src/test/java/com/thealgorithms/sorts/HeapSortTest.java
index 71a5ec3a7e66..90b2ebd68bc6 100644
--- a/src/test/java/com/thealgorithms/sorts/HeapSortTest.java
+++ b/src/test/java/com/thealgorithms/sorts/HeapSortTest.java
@@ -1,95 +1,8 @@
package com.thealgorithms.sorts;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-public class HeapSortTest {
- private HeapSort heapSort;
-
- @BeforeEach
- void setUp() {
- heapSort = new HeapSort();
- }
-
- @Test
- void shouldAcceptWhenEmptyArrayIsPassed() {
- Integer[] array = new Integer[]{};
- Integer[] expected = new Integer[]{};
-
- Integer[] sorted = heapSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenSingleValuedArrayIsPassed() {
- Integer[] array = new Integer[]{2};
- Integer[] expected = new Integer[]{2};
-
- Integer[] sorted = heapSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithAllPositiveValuesIsPassed() {
- Integer[] array = new Integer[]{60, 7, 55, 9, 999, 3};
- Integer[] expected = new Integer[]{3, 7, 9, 55, 60, 999};
-
- Integer[] sorted = heapSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithAllNegativeValuesIsPassed() {
- Integer[] array = new Integer[]{-60, -7, -55, -9, -999, -3};
- Integer[] expected = new Integer[]{-999, -60, -55, -9, -7, -3};
-
- Integer[] sorted = heapSort.sort(array);
-
- assertArrayEquals(expected, sorted);
+public class HeapSortTest extends SortingAlgorithmTest {
+ @Override
+ SortAlgorithm getSortAlgorithm() {
+ return new HeapSort();
}
-
- @Test
- void shouldAcceptWhenArrayWithRealNumberValuesIsPassed() {
- Integer[] array = new Integer[]{60, -7, 55, 9, -999, -3};
- Integer[] expected = new Integer[]{-999, -7, -3, 9, 55, 60};
-
- Integer[] sorted = heapSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithDuplicateValueIsPassed() {
- Integer[] array = new Integer[]{60, 7, 55, 55, 999, 3};
- Integer[] expected = new Integer[]{3, 7, 55, 55, 60, 999};
-
- Integer[] sorted = heapSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenStringValueArrayIsPassed() {
- String[] array = {"z", "a", "x", "b", "y"};
- String[] expected = {"a", "b", "x", "y", "z"};
-
- String[] sorted = heapSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenRandomArrayIsPassed() {
- int randomSize = SortUtilsRandomGenerator.generateInt(10_000);
- Double[] array = SortUtilsRandomGenerator.generateArray(randomSize);
- Double[] sorted = heapSort.sort(array);
- assertTrue(SortUtils.isSorted(sorted));
- }
-
}
diff --git a/src/test/java/com/thealgorithms/sorts/MergeSortTest.java b/src/test/java/com/thealgorithms/sorts/MergeSortTest.java
index 2f1277057851..af06e360a038 100644
--- a/src/test/java/com/thealgorithms/sorts/MergeSortTest.java
+++ b/src/test/java/com/thealgorithms/sorts/MergeSortTest.java
@@ -1,95 +1,8 @@
package com.thealgorithms.sorts;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class MergeSortTest {
-
- private MergeSort mergeSort;
-
- @BeforeEach
- void setUp() {
- mergeSort = new MergeSort();
- }
-
- @Test
- void shouldAcceptWhenEmptyArrayIsPassed() {
- Integer [] array = new Integer[]{};
- Integer [] expected = new Integer[]{};
-
- Integer []sorted = mergeSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenSingleValuedArrayIsPassed() {
- Integer [] array = new Integer[]{2};
- Integer [] expected = new Integer[]{2};
-
- Integer [] sorted = mergeSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithAllPositiveValuesIsPassed() {
- Integer [] array = new Integer[]{60, 7, 55, 9, 999, 3};
- Integer [] expected = new Integer[]{3, 7, 9, 55, 60, 999};
-
- Integer [] sorted = mergeSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithAllNegativeValuesIsPassed() {
- Integer [] array = new Integer[]{-60, -7, -55, -9, -999, -3};
- Integer [] expected = new Integer[]{-999, -60, -55, -9, -7, -3};
-
- Integer [] sorted = mergeSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithRealNumberValuesIsPassed() {
- Integer [] array = new Integer[]{60, -7, 55, 9, -999, -3};
- Integer [] expected = new Integer[]{-999, -7, -3, 9, 55, 60};
-
- Integer [] sorted = mergeSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithDuplicateValueIsPassed() {
- Integer [] array = new Integer[]{60, 7, 55, 55, 999, 3};
- Integer [] expected = new Integer[]{3, 7, 55, 55, 60, 999};
-
- Integer [] sorted = mergeSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenStringValueArrayIsPassed() {
- String[] array = {"z", "a", "x", "b", "y"};
- String[] expected = {"a", "b", "x", "y", "z"};
-
- String[] sorted = mergeSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenRandomArrayIsPassed() {
- int randomSize = SortUtilsRandomGenerator.generateInt(10_000);
- Double[] array = SortUtilsRandomGenerator.generateArray(randomSize);
- Double[] sorted = mergeSort.sort(array);
- assertTrue(SortUtils.isSorted(sorted));
+public class MergeSortTest extends SortingAlgorithmTest {
+ @Override
+ SortAlgorithm getSortAlgorithm() {
+ return new MergeSort();
}
}
diff --git a/src/test/java/com/thealgorithms/sorts/QuickSortTest.java b/src/test/java/com/thealgorithms/sorts/QuickSortTest.java
index 6d66f51eaaa1..fca57626b75f 100644
--- a/src/test/java/com/thealgorithms/sorts/QuickSortTest.java
+++ b/src/test/java/com/thealgorithms/sorts/QuickSortTest.java
@@ -1,62 +1,12 @@
package com.thealgorithms.sorts;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-
-import org.junit.jupiter.api.Test;
-
/**
* @author Akshay Dubey (https://github.com/itsAkshayDubey)
* @see QuickSort
*/
-class QuickSortTest {
-
- private QuickSort quickSort = new QuickSort();
-
- @Test
- void quickSortEmptyArrayShouldPass() {
- Integer[] array = {};
- Integer[] sorted = quickSort.sort(array);
- Integer[] expected = {};
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void quickSortSingleValueArrayShouldPass() {
- Integer[] array = { 7 };
- Integer[] sorted = quickSort.sort(array);
- Integer[] expected = { 7 };
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void quickSortWithIntegerArrayShouldPass() {
- Integer[] array = { 49, 4, 36, 9, 144, 1 };
- Integer[] sorted = quickSort.sort(array);
- Integer[] expected = { 1, 4, 9, 36, 49, 144 };
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void quickSortForArrayWithNegativeValuesShouldPass() {
- Integer[] array = { 49, -36, -144, -49, 1, 9 };
- Integer[] sorted = quickSort.sort(array);
- Integer[] expected = { -144, -49, -36, 1, 9, 49 };
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void quickSortForArrayWithDuplicateValuesShouldPass() {
- Integer[] array = { 36, 1, 49, 1, 4, 9 };
- Integer[] sorted = quickSort.sort(array);
- Integer[] expected = { 1, 1, 4, 9, 36, 49 };
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void quickSortWithStringArrayShouldPass() {
- String[] array = { "c", "a", "e", "b", "d" };
- String[] sorted = quickSort.sort(array);
- String[] expected = { "a", "b", "c", "d", "e" };
- assertArrayEquals(expected, sorted);
+class QuickSortTest extends SortingAlgorithmTest {
+ @Override
+ SortAlgorithm getSortAlgorithm() {
+ return new QuickSort();
}
}
diff --git a/src/test/java/com/thealgorithms/sorts/SortUtilsTest.java b/src/test/java/com/thealgorithms/sorts/SortUtilsTest.java
index bb558727906b..249c251dd470 100644
--- a/src/test/java/com/thealgorithms/sorts/SortUtilsTest.java
+++ b/src/test/java/com/thealgorithms/sorts/SortUtilsTest.java
@@ -2,6 +2,8 @@
import org.junit.jupiter.api.Test;
+import java.util.List;
+
import static org.junit.jupiter.api.Assertions.*;
class SortUtilsTest {
@@ -19,7 +21,7 @@ void isSortedWithSingleElement() {
}
@Test
- void isSortedTrue() {
+ void isSortedArrayTrue() {
Integer[] array = {1, 1, 2, 3, 5, 8, 11};
assertTrue(SortUtils.isSorted(array));
@@ -31,7 +33,7 @@ void isSortedTrue() {
}
@Test
- void isSortedFalse() {
+ void isSortedArrayFalse() {
Double[] array = {1.0, 3.0, -0.15};
assertFalse(SortUtils.isSorted(array));
@@ -41,4 +43,28 @@ void isSortedFalse() {
Integer[] array3 = {5, 4, 3, 2, 1};
assertFalse(SortUtils.isSorted(array3));
}
+
+ @Test
+ void isSortedListTrue() {
+ List list = List.of(1, 1, 2, 3, 5, 8, 11);
+ assertTrue(SortUtils.isSorted(list));
+
+ List identicalList = List.of(1, 1, 1, 1, 1);
+ assertTrue(SortUtils.isSorted(identicalList));
+
+ List doubles = List.of(-15.123, -15.111, 0.0, 0.12, 0.15);
+ assertTrue(SortUtils.isSorted(doubles));
+ }
+
+ @Test
+ void isSortedListFalse() {
+ List list = List.of(1.0, 3.0, -0.15);
+ assertFalse(SortUtils.isSorted(list));
+
+ List array2 = List.of(14, 15, 16, 1);
+ assertFalse(SortUtils.isSorted(array2));
+
+ List array3 = List.of(5, 4, 3, 2, 1);
+ assertFalse(SortUtils.isSorted(array3));
+ }
}
diff --git a/src/test/java/com/thealgorithms/sorts/SortingAlgorithmTest.java b/src/test/java/com/thealgorithms/sorts/SortingAlgorithmTest.java
new file mode 100644
index 000000000000..d7230f6da31c
--- /dev/null
+++ b/src/test/java/com/thealgorithms/sorts/SortingAlgorithmTest.java
@@ -0,0 +1,171 @@
+package com.thealgorithms.sorts;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public abstract class SortingAlgorithmTest {
+ abstract SortAlgorithm getSortAlgorithm();
+
+ @Test
+ void shouldAcceptWhenEmptyArrayIsPassed() {
+ Integer[] array = new Integer[]{};
+ Integer[] expected = new Integer[]{};
+
+ Integer[] sorted = getSortAlgorithm().sort(array);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenEmptyListIsPassed() {
+ List list = new ArrayList<>();
+ List expected = new ArrayList<>();
+
+ List sorted = getSortAlgorithm().sort(list);
+
+ assertIterableEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenSingleValuedArrayIsPassed() {
+ Integer[] array = new Integer[]{2};
+ Integer[] expected = new Integer[]{2};
+
+ Integer[] sorted = getSortAlgorithm().sort(array);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenSingleValuedListIsPassed() {
+ List list = List.of(2);
+ List expected = List.of(2);
+
+ List sorted = getSortAlgorithm().sort(list);
+
+ assertIterableEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenListWithAllPositiveValuesIsPassed() {
+ Integer[] array = new Integer[]{60, 7, 55, 9, 999, 3};
+ Integer[] expected = new Integer[]{3, 7, 9, 55, 60, 999};
+
+ Integer[] sorted = getSortAlgorithm().sort(array);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenArrayWithAllPositiveValuesIsPassed() {
+ List list = List.of(60, 7, 55, 9, 999, 3);
+ List expected = List.of(3, 7, 9, 55, 60, 999);
+
+ List sorted = getSortAlgorithm().sort(list);
+
+ assertIterableEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenArrayWithAllNegativeValuesIsPassed() {
+ Integer[] array = new Integer[]{-60, -7, -55, -9, -999, -3};
+ Integer[] expected = new Integer[]{-999, -60, -55, -9, -7, -3};
+
+ Integer[] sorted = getSortAlgorithm().sort(array);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenListWithAllNegativeValuesIsPassed() {
+ List list = List.of(-60, -7, -55, -9, -999, -3);
+ List expected = List.of(-999, -60, -55, -9, -7, -3);
+
+ List sorted = getSortAlgorithm().sort(list);
+
+ assertIterableEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenArrayWithRealNumberValuesIsPassed() {
+ Integer[] array = new Integer[]{60, -7, 55, 9, -999, -3};
+ Integer[] expected = new Integer[]{-999, -7, -3, 9, 55, 60};
+
+ Integer[] sorted = getSortAlgorithm().sort(array);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenListWithRealNumberValuesIsPassed() {
+ List list = List.of(60, -7, 55, 9, -999, -3);
+ List expected = List.of(-999, -7, -3, 9, 55, 60);
+
+ List sorted = getSortAlgorithm().sort(list);
+
+ assertIterableEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenArrayWithDuplicateValueIsPassed() {
+ Integer[] array = new Integer[]{60, 7, 55, 55, 999, 3};
+ Integer[] expected = new Integer[]{3, 7, 55, 55, 60, 999};
+
+ Integer[] sorted = getSortAlgorithm().sort(array);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenListWithDuplicateValueIsPassed() {
+ List list = List.of(60, 7, 55, 55, 999, 3);
+ List expected = List.of(3, 7, 55, 55, 60, 999);
+
+ List sorted = getSortAlgorithm().sort(list);
+
+ assertIterableEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenStringValueArrayIsPassed() {
+ String[] array = {"z", "a", "x", "b", "y"};
+ String[] expected = {"a", "b", "x", "y", "z"};
+
+ String[] sorted = getSortAlgorithm().sort(array);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenStringValueListIsPassed() {
+ List list = List.of("z", "a", "x", "b", "y");
+ List expected = List.of("a", "b", "x", "y", "z");
+
+ List sorted = getSortAlgorithm().sort(list);
+
+ assertIterableEquals(expected, sorted);
+ }
+
+ @Test
+ void shouldAcceptWhenRandomArrayIsPassed() {
+ int randomSize = SortUtilsRandomGenerator.generateInt(10_000);
+ Double[] array = SortUtilsRandomGenerator.generateArray(randomSize);
+ Double[] sorted = getSortAlgorithm().sort(array);
+ assertTrue(SortUtils.isSorted(sorted));
+ }
+
+ @Test
+ void shouldAcceptWhenRandomListIsPassed() {
+ int randomSize = SortUtilsRandomGenerator.generateInt(10_000);
+ Double[] array = SortUtilsRandomGenerator.generateArray(randomSize);
+ List list = List.of(array);
+ List sorted = getSortAlgorithm().sort(list);
+ assertTrue(SortUtils.isSorted(sorted));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/sorts/TimSortTest.java b/src/test/java/com/thealgorithms/sorts/TimSortTest.java
index b319aa232f32..85df96f5367f 100644
--- a/src/test/java/com/thealgorithms/sorts/TimSortTest.java
+++ b/src/test/java/com/thealgorithms/sorts/TimSortTest.java
@@ -5,91 +5,9 @@
import static org.junit.jupiter.api.Assertions.*;
-class TimSortTest {
-
- private TimSort timSort;
-
- @BeforeEach
- void setUp() {
- timSort = new TimSort();
+class TimSortTest extends SortingAlgorithmTest {
+ @Override
+ SortAlgorithm getSortAlgorithm() {
+ return new TimSort();
}
-
- @Test
- void shouldAcceptWhenEmptyArrayIsPassed() {
- Integer [] array = new Integer[]{};
- Integer [] expected = new Integer[]{};
-
- Integer []sorted = timSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenSingleValuedArrayIsPassed() {
- Integer [] array = new Integer[]{2};
- Integer [] expected = new Integer[]{2};
-
- Integer [] sorted = timSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithAllPositiveValuesIsPassed() {
- Integer [] array = new Integer[]{60, 7, 55, 9, 999, 3};
- Integer [] expected = new Integer[]{3, 7, 9, 55, 60, 999};
-
- Integer [] sorted = timSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithAllNegativeValuesIsPassed() {
- Integer [] array = new Integer[]{-60, -7, -55, -9, -999, -3};
- Integer [] expected = new Integer[]{-999, -60, -55, -9, -7, -3};
-
- Integer [] sorted = timSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithRealNumberValuesIsPassed() {
- Integer [] array = new Integer[]{60, -7, 55, 9, -999, -3};
- Integer [] expected = new Integer[]{-999, -7, -3, 9, 55, 60};
-
- Integer [] sorted = timSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenArrayWithDuplicateValueIsPassed() {
- Integer [] array = new Integer[]{60, 7, 55, 55, 999, 3};
- Integer [] expected = new Integer[]{3, 7, 55, 55, 60, 999};
-
- Integer [] sorted = timSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenStringValueArrayIsPassed() {
- String[] array = {"z", "a", "x", "b", "y"};
- String[] expected = {"a", "b", "x", "y", "z"};
-
- String[] sorted = timSort.sort(array);
-
- assertArrayEquals(expected, sorted);
- }
-
- @Test
- void shouldAcceptWhenRandomArrayIsPassed() {
- int randomSize = SortUtilsRandomGenerator.generateInt(10_000);
- Double[] array = SortUtilsRandomGenerator.generateArray(randomSize);
- Double[] sorted = timSort.sort(array);
- assertTrue(SortUtils.isSorted(sorted));
- }
-
}
From 1aed52ba582b2edad57551c60044b8b0c8a65331 Mon Sep 17 00:00:00 2001
From: Andrii Siriak
Date: Wed, 4 Jan 2023 10:11:45 +0200
Subject: [PATCH 0010/1088] Trigger builds for all changes
---
.github/workflows/build.yml | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index efd76cc7eb79..7e3feabdd260 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,17 +1,5 @@
name: Build
-on:
- push:
- paths:
- - 'src/**'
- - '**.yml'
- - '**.xml'
- - '**.Dockerfile'
- pull_request:
- paths:
- - 'src/**'
- - '**.yml'
- - '**.xml'
- - '**.Dockerfile'
+on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
From 9d86348cce26bc3ad8643cddb00d614085e8d230 Mon Sep 17 00:00:00 2001
From: Abinash Satapathy
Date: Wed, 4 Jan 2023 09:13:38 +0100
Subject: [PATCH 0011/1088] Update CONTRIBUTING.md (#3486)
---
CONTRIBUTING.md | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 31e0a7e7cf28..23ee1bb07a97 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,26 +1,28 @@
## How to contribute?
-#### **Did you find a bug?**
+### Did you find a bug?
-- **Ensure the bug was not already reported** by searching on GitHub under [Project Issues](https://github.com/TheAlgorithms/Java/issues).
+**Ensure the bug was not already reported** by searching on GitHub under [Project Issues](https://github.com/TheAlgorithms/Java/issues).
+ - If it is mentioned in the issues and you want to fix it, [fork](https://github.com/TheAlgorithms/Java/fork) the repository and submit your implementation in a pull request. The project maintainers will evaluate it.
+ - If the bug is **NOT** mentioned in the issues, [open a new issue](https://github.com/TheAlgorithms/Java/issues/new). Be sure to include a **title**, a clear **description** and a **test case** demonstrating the expected behavior that is not occurring.
-- Please avoid opening issues asking to be "assignedβ to a particular algorithm. This merely creates unnecessary noise for maintainers. Instead, please submit your implementation in a pull request and project maintainers will evaluate it.
+NOTE: *Please avoid opening issues asking to be "assigned" to a particular algorithm. This merely creates unnecessary noise for maintainers. Instead, please submit your implementation in a pull request and project maintainers will evaluate it.*
-- If you are unable to find an open issue referring to the same problem, depending on the type of issue follow the appropriate steps:
-#### **Do you want to contribute to the documentation?**
-- Please read the documentation here [Contributing to the Documentation](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md), [open a new issue](https://github.com/TheAlgorithms/Java/issues/new), make changes, and then create a pull request, it will be put under review and accepted if it is appropriate.
+### Do you want to contribute to the documentation?
+ - [Fork](https://github.com/TheAlgorithms/Java/fork) the repository and make necessary changes.
+ - Create a pull request.
+ - It will be put under review for approval.
+ - If approved, the requested changes will be merged to the repository.
-#### **Do you want to add a new feature?**
+### Do you want to add a new feature?
-- [Open a new issue](https://github.com/TheAlgorithms/Java/issues/new). Be sure to include a **title, clear description** and **test case** demonstrating the new feature you want to add to the project.
+- [Open a new issue](https://github.com/TheAlgorithms/Java/issues/new).
+- Be sure to include a **title**, a clear **description** and a **test case** demonstrating the new feature you want to add to the project.
-#### **Do you want to fix a bug?**
-- [Open a new issue](https://github.com/TheAlgorithms/Java/issues/new). Be sure to include a **title and a clear description** and a **test case** demonstrating the expected behavior that is not occurring.
-
-#### **Do you have questions about the source code?**
+### Do you have questions about the source code?
- Ask any question about how to use the repository in the [TheAlgorithms room in GITTER](https://gitter.im/TheAlgorithms/community?source=orgpage#) or [open a new issue](https://github.com/TheAlgorithms/Java/issues/new)
From 64181d6ea738278deee04e15c099970bf8a0da3f Mon Sep 17 00:00:00 2001
From: Om Shinde <66997973+newbieprogrammer17@users.noreply.github.com>
Date: Tue, 10 Jan 2023 13:00:22 +0530
Subject: [PATCH 0012/1088] Remove unnecessary import (#3809)
---
src/main/java/com/thealgorithms/backtracking/PowerSum.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/backtracking/PowerSum.java b/src/main/java/com/thealgorithms/backtracking/PowerSum.java
index 907c8f44c4ac..dc4738583358 100644
--- a/src/main/java/com/thealgorithms/backtracking/PowerSum.java
+++ b/src/main/java/com/thealgorithms/backtracking/PowerSum.java
@@ -1,6 +1,5 @@
package com.thealgorithms.backtracking;
-import java.util.Scanner;
/*
* Problem Statement :
From 5aa417b6aee6a4d9d5392f8590079a1342003989 Mon Sep 17 00:00:00 2001
From: Albina
Date: Thu, 12 Jan 2023 15:06:11 +0300
Subject: [PATCH 0013/1088] Added Zigzag Traversal of a Binary Tree (#3811)
* Added Zigzag Traversal of a Binary Tree
* fixed file name
Co-authored-by: Albina Gimaletdinova
---
.../datastructures/trees/ZigzagTraversal.java | 70 +++++++++++++++++++
.../trees/ZigzagTraversalTest.java | 30 ++++++++
2 files changed, 100 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/trees/ZigzagTraversal.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/ZigzagTraversalTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/ZigzagTraversal.java b/src/main/java/com/thealgorithms/datastructures/trees/ZigzagTraversal.java
new file mode 100644
index 000000000000..9026fdfaa041
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/trees/ZigzagTraversal.java
@@ -0,0 +1,70 @@
+package com.thealgorithms.datastructures.trees;
+
+import java.util.*;
+
+/**
+ * Given a binary tree.
+ * This code returns the zigzag level order traversal of its nodes' values.
+ * Binary tree:
+ * 7
+ * / \
+ * 6 3
+ * / \ / \
+ * 2 4 10 19
+ * Zigzag traversal:
+ * [[7], [3, 6], [2, 4, 10, 19]]
+ *
+ * This solution implements the breadth-first search (BFS) algorithm using a queue.
+ * 1. The algorithm starts with a root node. This node is added to a queue.
+ * 2. While the queue is not empty:
+ * - each time we enter the while-loop we get queue size. Queue size refers to the number of nodes at the current level.
+ * - we traverse all the level nodes in 2 ways: from left to right OR from right to left
+ * (this state is stored on `prevLevelFromLeftToRight` variable)
+ * - if the current node has children we add them to a queue
+ * - add level with nodes to a result.
+ *
+ * Complexities:
+ * O(N) - time, where N is the number of nodes in a binary tree
+ * O(N) - space, where N is the number of nodes in a binary tree
+ *
+ * @author Albina Gimaletdinova on 11/01/2023
+ */
+public class ZigzagTraversal {
+ public static List> traverse(BinaryTree.Node root) {
+ if (root == null) {
+ return new ArrayList<>();
+ }
+
+ List> result = new ArrayList<>();
+
+ // create a queue
+ Deque q = new ArrayDeque<>();
+ q.offer(root);
+ // start with writing nodes from left to right
+ boolean prevLevelFromLeftToRight = false;
+
+ while (!q.isEmpty()) {
+ int nodesOnLevel = q.size();
+ List level = new LinkedList<>();
+ // traverse all the level nodes
+ for (int i = 0; i < nodesOnLevel; i++) {
+ BinaryTree.Node node = q.poll();
+ if (prevLevelFromLeftToRight) {
+ level.add(0, node.data);
+ } else {
+ level.add(node.data);
+ }
+ if (node.left != null) {
+ q.offer(node.left);
+ }
+ if (node.right != null) {
+ q.offer(node.right);
+ }
+ }
+ // the next level node traversal will be from the other side
+ prevLevelFromLeftToRight = !prevLevelFromLeftToRight;
+ result.add(level);
+ }
+ return result;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/ZigzagTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/ZigzagTraversalTest.java
new file mode 100644
index 000000000000..11af07c57e0a
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/ZigzagTraversalTest.java
@@ -0,0 +1,30 @@
+package com.thealgorithms.datastructures.trees;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Albina Gimaletdinova on 11/01/2023
+ */
+public class ZigzagTraversalTest {
+ @Test
+ public void testRootNull() {
+ assertEquals(Collections.emptyList(), ZigzagTraversal.traverse(null));
+ }
+
+ @Test
+ public void testSingleNodeTree() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{50});
+ assertEquals(List.of(List.of(50)), ZigzagTraversal.traverse(root));
+ }
+
+ @Test
+ public void testZigzagTraversal() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{7, 6, 14, 2, 80, 100});
+ assertEquals(List.of(List.of(7), List.of(14, 6), List.of(2, 80, 100)), ZigzagTraversal.traverse(root));
+ }
+}
From 3b6e3edbfbcecbffeff09f7658b53b82bfbbd744 Mon Sep 17 00:00:00 2001
From: Albina Gimaletdinova
Date: Fri, 13 Jan 2023 16:56:15 +0300
Subject: [PATCH 0014/1088] Vertical order traversal refactoring, added unit
test (#3844)
Vertical order traversal refactoring, added test
---
.../trees/VerticalOrderTraversal.java | 32 ++++-------
.../trees/VerticalOrderTraversalTest.java | 53 +++++++++++++++++++
2 files changed, 63 insertions(+), 22 deletions(-)
create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversal.java b/src/main/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversal.java
index f90fab52b3d1..15fd348ea1eb 100644
--- a/src/main/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversal.java
+++ b/src/main/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversal.java
@@ -22,23 +22,13 @@
*/
public class VerticalOrderTraversal {
- public static void main(String[] args) {
- BinaryTree tree = new BinaryTree();
- tree.put(5);
- tree.put(6);
- tree.put(3);
- tree.put(1);
- tree.put(4);
- BinaryTree.Node root = tree.getRoot();
- ArrayList ans = verticalTraversal(root);
- for (int i : ans) {
- System.out.print(i + " ");
+ /*Function that receives a root Node and prints the tree
+ in Vertical Order.*/
+ public static ArrayList verticalTraversal(BinaryTree.Node root) {
+ if (root == null) {
+ return new ArrayList<>();
}
- }
- /*Function that receives a root Node and prints the tree
- in Vertical Order.*/
- private static ArrayList verticalTraversal(BinaryTree.Node root) {
/*Queue to store the Nodes.*/
Queue queue = new LinkedList<>();
@@ -84,21 +74,19 @@ private static ArrayList verticalTraversal(BinaryTree.Node root) {
to the respective ArrayList present at that
index. */
map.get(index.peek()).add(queue.peek().data);
- max = (int) Math.max(max, index.peek());
- min = (int) Math.min(min, index.peek());
- /*The Node and its index are removed
+ max = Math.max(max, index.peek());
+ min = Math.min(min, index.peek());
+ /*The Node and its index are removed
from their respective queues.*/
index.poll();
queue.poll();
}
/*Finally map data is printed here which has keys
- from min to max. Each ArrayList represents a
+ from min to max. Each ArrayList represents a
vertical column that is added in ans ArrayList.*/
ArrayList ans = new ArrayList<>();
for (int i = min; i <= max; i++) {
- for (int j = 0; j < map.get(i).size(); j++) {
- ans.add(map.get(i).get(j));
- }
+ ans.addAll(map.get(i));
}
return ans;
}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java
new file mode 100644
index 000000000000..42875e4ffa70
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java
@@ -0,0 +1,53 @@
+package com.thealgorithms.datastructures.trees;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Albina Gimaletdinova on 13/01/2023
+ */
+public class VerticalOrderTraversalTest {
+ @Test
+ public void testRootNull() {
+ assertEquals(Collections.emptyList(), VerticalOrderTraversal.verticalTraversal(null));
+ }
+
+ @Test
+ public void testSingleNodeTree() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{50});
+ assertEquals(List.of(50), VerticalOrderTraversal.verticalTraversal(root));
+ }
+
+ /*
+ 1
+ / \
+ 2 3
+ /\ /\
+ 4 5 6 7
+ */
+ @Test
+ public void testVerticalTraversalCompleteTree() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
+ assertEquals(List.of(4, 2, 1, 5, 6, 3, 7), VerticalOrderTraversal.verticalTraversal(root));
+ }
+
+ /*
+ 1
+ / \
+ 2 3
+ /\ /\
+ 4 56 7
+ / \
+ 8 9
+ */
+ @Test
+ public void testVerticalTraversalDifferentHeight() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(
+ new Integer[]{1, 2, 3, 4, 5, 6, 7, null, null, 8, null, null, 9});
+ assertEquals(List.of(4, 2, 8, 1, 5, 6, 3, 9, 7), VerticalOrderTraversal.verticalTraversal(root));
+ }
+}
From 44c05bf7db34c9e0458b82b82bf7b0aa69421af7 Mon Sep 17 00:00:00 2001
From: thanoskiver <83243257+thanoskiver@users.noreply.github.com>
Date: Fri, 13 Jan 2023 21:22:45 +0200
Subject: [PATCH 0015/1088] Add Shortest Job First Scheduling (#3843)
---
.../java/com/thealgorithms/others/SJF.java | 199 ------------------
.../scheduling/SJFScheduling.java | 115 ++++++++++
.../scheduling/SJFSchedulingTest.java | 120 +++++++++++
3 files changed, 235 insertions(+), 199 deletions(-)
delete mode 100644 src/main/java/com/thealgorithms/others/SJF.java
create mode 100644 src/main/java/com/thealgorithms/scheduling/SJFScheduling.java
create mode 100644 src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java
diff --git a/src/main/java/com/thealgorithms/others/SJF.java b/src/main/java/com/thealgorithms/others/SJF.java
deleted file mode 100644
index 171474123029..000000000000
--- a/src/main/java/com/thealgorithms/others/SJF.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package com.thealgorithms.others;
-
-/**
- *
- *
- * Shortest job first.
- *
- *
- * Shortest job first (SJF) or shortest job next, is a scheduling policy that
- * selects the waiting process with the smallest execution time to execute next
- * Shortest Job first has the advantage of having minimum average waiting time
- * among all scheduling algorithms. It is a Greedy Algorithm. It may cause
- * starvation if shorter processes keep coming. This problem has been solved
- * using the concept of aging.
- *
- * @author shivg7706
- * @since 2018/10/27
- */
-import java.util.*;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Scanner;
-
-class Process {
-
- public int pid;
- public int arrivalTime;
- public int burstTime;
- public int priority;
- public int turnAroundTime;
- public int waitTime;
- public int remainingTime;
-}
-
-class Schedule {
-
- private int noOfProcess;
- private int timer = 0;
- private ArrayList processes;
- private ArrayList remainingProcess;
- private ArrayList gantChart;
- private float burstAll;
- private Map> arrivals;
-
- Schedule() {
- Scanner in = new Scanner(System.in);
-
- processes = new ArrayList();
- remainingProcess = new ArrayList();
-
- gantChart = new ArrayList<>();
- arrivals = new HashMap<>();
-
- System.out.print("Enter the no. of processes: ");
- noOfProcess = in.nextInt();
- System.out.println(
- "Enter the arrival, burst and priority of processes"
- );
- for (int i = 0; i < noOfProcess; i++) {
- Process p = new Process();
- p.pid = i;
- p.arrivalTime = in.nextInt();
- p.burstTime = in.nextInt();
- p.priority = in.nextInt();
- p.turnAroundTime = 0;
- p.waitTime = 0;
- p.remainingTime = p.burstTime;
-
- if (arrivals.get(p.arrivalTime) == null) {
- arrivals.put(p.arrivalTime, new ArrayList());
- }
- arrivals.get(p.arrivalTime).add(p);
- processes.add(p);
- burstAll += p.burstTime;
- }
- in.close();
- }
-
- void startScheduling() {
- processes.sort(
- new Comparator() {
- @Override
- public int compare(Process a, Process b) {
- return a.arrivalTime - b.arrivalTime;
- }
- }
- );
-
- while (!(arrivals.size() == 0 && remainingProcess.size() == 0)) {
- removeFinishedProcess();
- if (arrivals.get(timer) != null) {
- remainingProcess.addAll(arrivals.get(timer));
- arrivals.remove(timer);
- }
-
- remainingProcess.sort(
- new Comparator() {
- private int alpha = 6;
- private int beta = 1;
-
- @Override
- public int compare(Process a, Process b) {
- int aRem = a.remainingTime;
- int bRem = b.remainingTime;
- int aprior = a.priority;
- int bprior = b.priority;
- return (
- (alpha * aRem + beta * aprior) -
- (alpha * bRem + beta * bprior)
- );
- }
- }
- );
-
- int k = timeElapsed(timer);
- ageing(k);
- timer++;
- }
-
- System.out.println("Total time required: " + (timer - 1));
- }
-
- void removeFinishedProcess() {
- ArrayList completed = new ArrayList();
- for (int i = 0; i < remainingProcess.size(); i++) {
- if (remainingProcess.get(i).remainingTime == 0) {
- completed.add(i);
- }
- }
-
- for (int i = 0; i < completed.size(); i++) {
- int pid = remainingProcess.get(completed.get(i)).pid;
- processes.get(pid).waitTime =
- remainingProcess.get(completed.get(i)).waitTime;
- remainingProcess.remove(remainingProcess.get(completed.get(i)));
- }
- }
-
- public int timeElapsed(int i) {
- if (!remainingProcess.isEmpty()) {
- gantChart.add(i, remainingProcess.get(0).pid);
- remainingProcess.get(0).remainingTime--;
- return 1;
- }
- return 0;
- }
-
- public void ageing(int k) {
- for (int i = k; i < remainingProcess.size(); i++) {
- remainingProcess.get(i).waitTime++;
- if (remainingProcess.get(i).waitTime % 7 == 0) {
- remainingProcess.get(i).priority--;
- }
- }
- }
-
- public void solve() {
- System.out.println("Gant chart ");
- for (int i = 0; i < gantChart.size(); i++) {
- System.out.print(gantChart.get(i) + " ");
- }
- System.out.println();
-
- float waitTimeTot = 0;
- float tatTime = 0;
-
- for (int i = 0; i < noOfProcess; i++) {
- processes.get(i).turnAroundTime =
- processes.get(i).waitTime + processes.get(i).burstTime;
-
- waitTimeTot += processes.get(i).waitTime;
- tatTime += processes.get(i).turnAroundTime;
-
- System.out.println(
- "Process no.: " +
- i +
- " Wait time: " +
- processes.get(i).waitTime +
- " Turn Around Time: " +
- processes.get(i).turnAroundTime
- );
- }
-
- System.out.println(
- "Average Waiting Time: " + waitTimeTot / noOfProcess
- );
- System.out.println("Average TAT Time: " + tatTime / noOfProcess);
- System.out.println("Throughput: " + (float) noOfProcess / (timer - 1));
- }
-}
-
-public class SJF {
-
- public static void main(String[] args) {
- Schedule s = new Schedule();
- s.startScheduling();
- s.solve();
- }
-}
diff --git a/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java b/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java
new file mode 100644
index 000000000000..bf3a9f00fae0
--- /dev/null
+++ b/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java
@@ -0,0 +1,115 @@
+package com.thealgorithms.scheduling;
+
+import com.thealgorithms.devutils.entities.ProcessDetails;
+
+import java.util.ArrayList;
+
+/**
+ * Implementation of Shortest Job First Algorithm: The algorithm allows the waiting process with the minimal burst time to be executed first.
+ * see more here: https://www.guru99.com/shortest-job-first-sjf-scheduling.html
+ */
+
+public class SJFScheduling {
+ protected ArrayList processes;
+ protected ArrayListschedule ;
+
+ /**
+ * a simple constructor
+ * @param processes a list of processes the user wants to schedule
+ * it also sorts the processes based on the time of their arrival
+ */
+ SJFScheduling(final ArrayList processes) {
+ this.processes = processes;
+ schedule=new ArrayList<>();
+ sortByArrivalTime();
+ }
+protected void sortByArrivalTime() {
+ int size=processes.size(),i,j;
+ ProcessDetails temp;
+ for(i=0;iprocesses.get(j+1).getArrivalTime())
+ {
+ temp=processes.get(j);
+ processes.set(j,processes.get(j+1));
+ processes.set(j+1,temp);
+ }
+ }
+ }
+
+}
+
+ /**
+ * this functions returns the order of the executions
+ */
+
+ public void scheduleProcesses() {
+ ArrayList ready=new ArrayList<>();
+
+ int size = processes.size(),runtime,time=0;
+ int executed=0,j,k=0;
+ ProcessDetails running;
+
+ if (size == 0) {
+ return;
+ }
+
+
+ while(executed ReadyProcesses) {
+ if (ReadyProcesses.isEmpty()){
+ return null;
+ }
+ int i,size = ReadyProcesses.size();
+ int minBurstTime = ReadyProcesses.get(0).getBurstTime(), temp, positionOfShortestJob = 0;
+
+
+ for (i = 1; i < size; i++) {
+ temp = ReadyProcesses.get(i).getBurstTime();
+ if (minBurstTime > temp ) {
+ minBurstTime = temp;
+ positionOfShortestJob = i;
+ }
+ }
+
+ return ReadyProcesses.get(positionOfShortestJob);
+ }
+
+
+
+
+
+ }
+
diff --git a/src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java
new file mode 100644
index 000000000000..8ba3b6795d86
--- /dev/null
+++ b/src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java
@@ -0,0 +1,120 @@
+package com.thealgorithms.scheduling;
+
+import com.thealgorithms.devutils.entities.ProcessDetails;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class SJFSchedulingTest {
+ private ArrayList process;
+ void initialisation0()
+ {
+
+ process=new ArrayList<>();
+ process.add(new ProcessDetails("1",0 ,6));
+ process.add(new ProcessDetails("2",1,2));
+ }
+ void initialisation1()
+ {
+
+ process=new ArrayList<>();
+ process.add(new ProcessDetails("1",0 ,6));
+ process.add(new ProcessDetails("2",1,2));
+ process.add(new ProcessDetails("3",4 ,3));
+ process.add(new ProcessDetails("4",3,1));
+ process.add(new ProcessDetails("5",6 ,4));
+ process.add(new ProcessDetails("6",5,5));
+ }
+
+ void initialisation2()
+ {
+
+ process=new ArrayList<>();
+ process.add(new ProcessDetails("1",0 ,3));
+ process.add(new ProcessDetails("2",1,2));
+ process.add(new ProcessDetails("3",2 ,1));
+
+ }
+ void initialisation3(){
+ process=new ArrayList<>();
+ process.add(new ProcessDetails("1",0 ,3));
+ process.add(new ProcessDetails("2",5,2));
+ process.add(new ProcessDetails("3",9 ,1));
+ }
+ @Test
+ void constructor()
+ {
+ initialisation0();
+ SJFScheduling a=new SJFScheduling(process);
+ assertEquals( 6,a.processes.get(0).getBurstTime());
+ assertEquals( 2,a.processes.get(1).getBurstTime());
+ }
+
+ @Test
+ void sort()
+ {
+ initialisation1();
+ SJFScheduling a=new SJFScheduling(process);
+ a.sortByArrivalTime();
+ assertEquals("1",a.processes.get(0).getProcessId());
+ assertEquals("2",a.processes.get(1).getProcessId());
+ assertEquals("3",a.processes.get(3).getProcessId());
+ assertEquals("4",a.processes.get(2).getProcessId());
+ assertEquals("5",a.processes.get(5).getProcessId());
+ assertEquals("6",a.processes.get(4).getProcessId());
+
+ }
+
+ @Test
+ void scheduling(){
+ initialisation1();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertEquals( "1" , a.schedule.get(0));
+ assertEquals( "4" , a.schedule.get(1));
+ assertEquals( "2" , a.schedule.get(2));
+ assertEquals( "3" , a.schedule.get(3));
+ assertEquals("5" , a.schedule.get(4));
+ assertEquals( "6", a.schedule.get(5));
+
+
+ }
+
+ @Test
+ void schedulingOf_TwoProcesses(){
+ initialisation0();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertEquals( "1" , a.schedule.get(0));
+ assertEquals( "2" , a.schedule.get(1));
+ }
+
+ @Test
+ void schedulingOfA_ShortestJobArrivingLast(){
+ initialisation2();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertEquals( "1" , a.schedule.get(0));
+ assertEquals( "3" , a.schedule.get(1));
+ assertEquals( "2" , a.schedule.get(2));
+ }
+ @Test
+ void scheduling_WithProcessesNotComingBackToBack(){
+ initialisation3();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertEquals( "1" , a.schedule.get(0));
+ assertEquals( "2" , a.schedule.get(1));
+ assertEquals( "3" , a.schedule.get(2));
+ }
+ @Test
+ void schedulingOf_nothing(){
+ process=new ArrayList<>();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertTrue( a.schedule.isEmpty());
+
+ }
+}
\ No newline at end of file
From 351e85d264432c1172cd28bb3da542cf9e1ad456 Mon Sep 17 00:00:00 2001
From: Albina Gimaletdinova
Date: Fri, 13 Jan 2023 23:07:56 +0300
Subject: [PATCH 0016/1088] Added same trees algorithm check with a unit test
(#3845)
Co-authored-by: Debasish Biswas
---
.../datastructures/trees/SameTreesCheck.java | 82 +++++++++++++++++++
.../trees/SameTreesCheckTest.java | 71 ++++++++++++++++
2 files changed, 153 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/trees/SameTreesCheck.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/SameTreesCheckTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/SameTreesCheck.java b/src/main/java/com/thealgorithms/datastructures/trees/SameTreesCheck.java
new file mode 100644
index 000000000000..6a2258b5e065
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/trees/SameTreesCheck.java
@@ -0,0 +1,82 @@
+package com.thealgorithms.datastructures.trees;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+/**
+ * Given 2 binary trees.
+ * This code checks whether they are the same (structurally identical and have the same values) or not.
+ *
+ * Example:
+ * 1. Binary trees:
+ * 1 1
+ * / \ / \
+ * 2 3 2 3
+ * /\ /\ /\ /\
+ * 4 5 6 7 4 5 6 7
+ * These trees are the same, so the code returns 'true'.
+ *
+ * 2. Binary trees:
+ * 1 1
+ * / \
+ * 2 2
+ * These trees are NOT the same (the structure differs), so the code returns 'false'.
+ *
+ * This solution implements the breadth-first search (BFS) algorithm.
+ * For each tree we create a queue and iterate the trees using these queues.
+ * On each step we check the nodes for equality, and if the nodes are not the same, return false.
+ * Otherwise, add children nodes to the queues and continue traversing the trees.
+ *
+ * Complexities:
+ * O(N) - time, where N is the number of nodes in a binary tree,
+ * O(N) - space, where N is the number of nodes in a binary tree.
+ *
+ * @author Albina Gimaletdinova on 13/01/2023
+ */
+public class SameTreesCheck {
+ public static boolean check(BinaryTree.Node p, BinaryTree.Node q) {
+ if (p == null && q == null) {
+ return true;
+ }
+ if (p == null || q == null) {
+ return false;
+ }
+
+ Deque q1 = new ArrayDeque<>();
+ Deque q2 = new ArrayDeque<>();
+ q1.add(p);
+ q2.add(q);
+ while (!q1.isEmpty() && !q2.isEmpty()) {
+ BinaryTree.Node first = q1.poll();
+ BinaryTree.Node second = q2.poll();
+ // check that some node can be null
+ // if the check is true: both nodes are null or both nodes are not null
+ if (!equalNodes(first, second)) return false;
+
+ if (first != null) {
+ if (!equalNodes(first.left, second.left)) return false;
+ if (first.left != null) {
+ q1.add(first.left);
+ q2.add(second.left);
+ }
+
+ if (!equalNodes(first.right, second.right)) return false;
+ if (first.right != null) {
+ q1.add(first.right);
+ q2.add(second.right);
+ }
+ }
+ }
+ return true;
+ }
+
+ private static boolean equalNodes(BinaryTree.Node p, BinaryTree.Node q) {
+ if (p == null && q == null) {
+ return true;
+ }
+ if (p == null || q == null) {
+ return false;
+ }
+ return p.data == q.data;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/SameTreesCheckTest.java b/src/test/java/com/thealgorithms/datastructures/trees/SameTreesCheckTest.java
new file mode 100644
index 000000000000..365ee99f75d9
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/SameTreesCheckTest.java
@@ -0,0 +1,71 @@
+package com.thealgorithms.datastructures.trees;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author Albina Gimaletdinova on 12/01/2023
+ */
+public class SameTreesCheckTest {
+ @Test
+ public void testBothRootsAreNull() {
+ assertTrue(SameTreesCheck.check(null, null));
+ }
+
+ @Test
+ public void testOneRootIsNull() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{100});
+ assertFalse(SameTreesCheck.check(root, null));
+ }
+
+ @Test
+ public void testSingleNodeTreesAreSame() {
+ final BinaryTree.Node p = TreeTestUtils.createTree(new Integer[]{100});
+ final BinaryTree.Node q = TreeTestUtils.createTree(new Integer[]{100});
+ assertTrue(SameTreesCheck.check(p, q));
+ }
+
+ /*
+ 1 1
+ / \ / \
+ 2 3 2 3
+ /\ /\ /\ /\
+ 4 5 6 7 4 5 6 7
+ */
+ @Test
+ public void testSameTreesIsSuccessful() {
+ final BinaryTree.Node p = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
+ final BinaryTree.Node q = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
+ assertTrue(SameTreesCheck.check(p, q));
+ }
+
+
+ /*
+ 1 1
+ / \ / \
+ 2 3 2 3
+ /\ /\ /\ /
+ 4 5 6 7 4 5 6
+ */
+ @Test
+ public void testSameTreesFails() {
+ final BinaryTree.Node p = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
+ final BinaryTree.Node q = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6});
+ assertFalse(SameTreesCheck.check(p, q));
+ }
+
+ /*
+ 1 1
+ / \
+ 2 2
+ */
+ @Test
+ public void testTreesWithDifferentStructure() {
+ final BinaryTree.Node p = TreeTestUtils.createTree(new Integer[]{1, 2});
+ final BinaryTree.Node q = TreeTestUtils.createTree(new Integer[]{1, null, 2});
+ assertFalse(SameTreesCheck.check(p, q));
+ }
+}
+
From d5f140458a1c2fc95ef91a7790fd98bfbca4e141 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?sadiul-hakim=E2=98=AA=EF=B8=8F?=
<92100853+sadiul-hakim@users.noreply.github.com>
Date: Sat, 14 Jan 2023 16:01:03 +0600
Subject: [PATCH 0017/1088] Add two algorithms with matrixes (#3364)
---
.../others/PrintAMatrixInSpiralOrder.java | 65 +++++++++++++++++++
.../SearchInARowAndColWiseSortedMatrix.java | 37 +++++++++++
.../others/TestPrintMatrixInSpiralOrder.java | 35 ++++++++++
...estSearchInARowAndColWiseSortedMatrix.java | 38 +++++++++++
4 files changed, 175 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/others/PrintAMatrixInSpiralOrder.java
create mode 100644 src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java
create mode 100644 src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java
create mode 100644 src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java
diff --git a/src/main/java/com/thealgorithms/others/PrintAMatrixInSpiralOrder.java b/src/main/java/com/thealgorithms/others/PrintAMatrixInSpiralOrder.java
new file mode 100644
index 000000000000..d2065085d8c6
--- /dev/null
+++ b/src/main/java/com/thealgorithms/others/PrintAMatrixInSpiralOrder.java
@@ -0,0 +1,65 @@
+package com.thealgorithms.others;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PrintAMatrixInSpiralOrder {
+ /**
+ * Search a key in row and column wise sorted matrix
+ *
+ * @param matrix matrix to be searched
+ * @param row number of rows matrix has
+ * @param col number of columns matrix has
+ * @author Sadiul Hakim : https://github.com/sadiul-hakim
+ */
+
+ public List print(int[][] matrix, int row, int col) {
+
+ // r traverses matrix row wise from first
+ int r = 0;
+ // c traverses matrix column wise from first
+ int c = 0;
+ int i;
+
+ List result = new ArrayList<>();
+
+ while (r < row && c < col) {
+ // print first row of matrix
+ for (i = c; i < col; i++) {
+ result.add(matrix[r][i]);
+ }
+
+ // increase r by one because first row printed
+ r++;
+
+ // print last column
+ for (i = r; i < row; i++) {
+ result.add(matrix[i][col - 1]);
+ }
+
+ // decrease col by one because last column has been printed
+ col--;
+
+ // print rows from last except printed elements
+ if (r < row) {
+ for (i = col - 1; i >= c; i--) {
+ result.add(matrix[row - 1][i]);
+ }
+
+ row--;
+
+ }
+
+ // print columns from first except printed elements
+ if (c < col) {
+ for (i = row - 1; i >= r; i--) {
+ result.add(matrix[i][c]);
+ }
+ c++;
+ }
+
+ }
+ return result;
+ }
+
+}
diff --git a/src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java b/src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java
new file mode 100644
index 000000000000..c92569cf1086
--- /dev/null
+++ b/src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java
@@ -0,0 +1,37 @@
+package com.thealgorithms.searches;
+
+import java.util.Arrays;
+
+public class SearchInARowAndColWiseSortedMatrix {
+ /**
+ * Search a key in row and column wise sorted matrix
+ *
+ * @param matrix matrix to be searched
+ * @param value Key being searched for
+ * @author Sadiul Hakim : https://github.com/sadiul-hakim
+ */
+
+ public int[] search(int[][] matrix, int value) {
+ int n = matrix.length;
+ // This variable iterates over rows
+ int i = 0;
+ // This variable iterates over columns
+ int j = n - 1;
+ int[] result = { -1, -1 };
+
+ while (i < n && j >= 0) {
+ if (matrix[i][j] == value) {
+ result[0] = i;
+ result[1] = j;
+ return result;
+ }
+ if (value > matrix[i][j]) {
+ i++;
+ } else {
+ j--;
+ }
+
+ }
+ return result;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java b/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java
new file mode 100644
index 000000000000..867311e1bce1
--- /dev/null
+++ b/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java
@@ -0,0 +1,35 @@
+package com.thealgorithms.others;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class TestPrintMatrixInSpiralOrder {
+ @Test
+ public void testOne() {
+ int[][] matrix = {
+ { 3, 4, 5, 6, 7 },
+ { 8, 9, 10, 11, 12 },
+ { 14, 15, 16, 17, 18 },
+ { 23, 24, 25, 26, 27 },
+ { 30, 31, 32, 33, 34 }
+ };
+ var printClass = new PrintAMatrixInSpiralOrder();
+ List res = printClass.print(matrix, matrix.length, matrix[0].length);
+ List list = List.of(3, 4, 5, 6, 7, 12, 18, 27, 34, 33, 32, 31, 30, 23, 14, 8, 9, 10, 11, 17, 26, 25,
+ 24, 15, 16);
+ assertIterableEquals(res, list);
+ }
+
+ @Test
+ public void testTwo() {
+ int[][] matrix = {
+ { 2, 2 }
+ };
+ var printClass = new PrintAMatrixInSpiralOrder();
+ List res = printClass.print(matrix, matrix.length, matrix[0].length);
+ List list = List.of(2, 2);
+ assertIterableEquals(res, list);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java b/src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java
new file mode 100644
index 000000000000..0dcc6186fa9b
--- /dev/null
+++ b/src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java
@@ -0,0 +1,38 @@
+package com.thealgorithms.searches;
+
+import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Test;
+
+public class TestSearchInARowAndColWiseSortedMatrix {
+ @Test
+ public void searchItem() {
+ int[][] matrix = {
+ { 3, 4, 5, 6, 7 },
+ { 8, 9, 10, 11, 12 },
+ { 14, 15, 16, 17, 18 },
+ { 23, 24, 25, 26, 27 },
+ { 30, 31, 32, 33, 34 }
+ };
+
+ var test = new SearchInARowAndColWiseSortedMatrix();
+ int[] res = test.search(matrix, 16);
+ int[] expectedResult = { 2, 2 };
+ assertArrayEquals(expectedResult, res);
+ }
+
+ @Test
+ public void notFound() {
+ int[][] matrix = {
+ { 3, 4, 5, 6, 7 },
+ { 8, 9, 10, 11, 12 },
+ { 14, 15, 16, 17, 18 },
+ { 23, 24, 25, 26, 27 },
+ { 30, 31, 32, 33, 34 }
+ };
+
+ var test = new SearchInARowAndColWiseSortedMatrix();
+ int[] res = test.search(matrix, 96);
+ int[] expectedResult = { -1, -1 };
+ assertArrayEquals(expectedResult, res);
+ }
+}
From b6c1d250f4539db7c8b275ea162ab19b5e40ac3d Mon Sep 17 00:00:00 2001
From: eloibru <74415517+eloibru@users.noreply.github.com>
Date: Sat, 14 Jan 2023 11:22:15 +0100
Subject: [PATCH 0018/1088] Add Conway Sequence (#3807)
Co-authored-by: Bruno Eloi
Co-authored-by: Andrii Siriak
---
.../java/com/thealgorithms/others/Conway.java | 36 ++++++++++++++++++
.../com/thealgorithms/others/ConwayTest.java | 37 +++++++++++++++++++
2 files changed, 73 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/others/Conway.java
create mode 100644 src/test/java/com/thealgorithms/others/ConwayTest.java
diff --git a/src/main/java/com/thealgorithms/others/Conway.java b/src/main/java/com/thealgorithms/others/Conway.java
new file mode 100644
index 000000000000..7a034d963633
--- /dev/null
+++ b/src/main/java/com/thealgorithms/others/Conway.java
@@ -0,0 +1,36 @@
+package com.thealgorithms.others;
+
+import java.util.*;
+
+public class Conway {
+
+ /*
+ * This class will generate the conway sequence also known as the look and say sequence.
+ * To generate a member of the sequence from the previous member, read off the digits of the previous member, counting the number of digits in groups of the same digit. For example:
+ *1 is read off as "one 1" or 11.
+ *11 is read off as "two 1s" or 21.
+ *21 is read off as "one 2, one 1" or 1211.
+ *1211 is read off as "one 1, one 2, two 1s" or 111221.
+ *111221 is read off as "three 1s, two 2s, one 1" or 312211.
+ * https://en.wikipedia.org/wiki/Look-and-say_sequence
+ * */
+
+ private static final StringBuilder builder = new StringBuilder();
+
+ protected static List generateList(String originalString, int maxIteration) {
+ List numbers = new ArrayList<>();
+ for(int i=0; i builder.append(s.length()).append(s.charAt(0)));
+ return builder.toString();
+ }
+}
diff --git a/src/test/java/com/thealgorithms/others/ConwayTest.java b/src/test/java/com/thealgorithms/others/ConwayTest.java
new file mode 100644
index 000000000000..04b357949767
--- /dev/null
+++ b/src/test/java/com/thealgorithms/others/ConwayTest.java
@@ -0,0 +1,37 @@
+package com.thealgorithms.others;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ConwayTest {
+ @Test
+ public void testGenerateWith1(){
+ assertEquals("31131211131221", Conway.generateList("1", 8).get(7));
+ }
+
+ @Test
+ public void testGenerateWith123456(){
+ assertEquals("13211321322113311213212312311211131122211213211331121321122112133221123113112221131112212211131221121321131211132221123113112221131112311332211211131221131211132211121312211231131112311211232221143113112221131112311332111213122112311311123112112322211531131122211311123113321112131221123113111231121123222116", Conway.generateList("123456", 20).get(11));
+ }
+
+ @Test
+ public void testGenerateWith1A1Z3E1R1T3G1F1D2E1S1C(){
+ assertEquals("311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311222112111331121113112221121113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111231133221121113311211131122211211131221131112311332211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213211322111213111213211231131211132211121311222113321132211221121332211A311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311222112111331121113112221121113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111231133221121113311211131122211211131221131112311332211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213211322111213111213211231131211132211121311222113321132211221121332211Z111312211312111322212321121113121112131112132112311321322112111312212321121113122112131112131221121321132132211231131122111213122112311311222113111221131221221321132132211331121321231231121113112221121321133112132112211213322112311311222113111231133211121312211231131122211322311311222112111312211311123113322112132113212231121113112221121321132122211322212221121123222112111312211312111322212321121113121112131112132112311321322112111312212321121113122112131112131221121321132132211231131122211331121321232221121113122113121122132112311321322112111312211312113221133211322112211213322112132113213221133112132123123112111311222112132113311213211231232112311311222112111312211311123113322112132113213221133112132123222113221321132132211331121321232221123113112221131112311322311211131122211213211331121321122112133221121113122113121113222123112221221321132132211231131122211331121321232221121113122113121113222123113221231231121113213221231221132221222112112322211E311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311222112111331121113112221121113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111231133221121113311211131122211211131221131112311332211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213211322111213111213211231131211132211121311222113321132211221121332211R311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311222112111331121113112221121113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111231133221121113311211131122211211131221131112311332211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213211322111213111213211231131211132211121311222113321132211221121332211T111312211312111322212321121113121112131112132112311321322112111312212321121113122112131112131221121321132132211231131122111213122112311311222113111221131221221321132132211331121321231231121113112221121321133112132112211213322112311311222113111231133211121312211231131122211322311311222112111312211311123113322112132113212231121113112221121321132122211322212221121123222112111312211312111322212321121113121112131112132112311321322112111312212321121113122112131112131221121321132132211231131122211331121321232221121113122113121122132112311321322112111312211312113221133211322112211213322112132113213221133112132123123112111311222112132113311213211231232112311311222112111312211311123113322112132113213221133112132123222113221321132132211331121321232221123113112221131112311322311211131122211213211331121321122112133221121113122113121113222123112221221321132132211231131122211331121321232221121113122113121113222123113221231231121113213221231221132221222112112322211G311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311222112111331121113112221121113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111231133221121113311211131122211211131221131112311332211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213211322111213111213211231131211132211121311222113321132211221121332211F311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311222112111331121113112221121113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111231133221121113311211131122211211131221131112311332211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213211322111213111213211231131211132211121311222113321132211221121332211D111312211312111322212321121113121112131112132112311321322112111312212321121113122112131112131221121321132132211231131122211331121321232221121113122113121122132112311321322112111312211312111322211213111213122112132113121113222112132113213221133112132123222112311311222113111231132231121113112221121321133112132112211213322112111312211312111322212311222122132113213221123113112221133112132123222112111312211312111322212311322123123112111321322123122113222122211211232221121113122113121113222123211211131211121311121321123113213221121113122123211211131221121311121312211213211321322112311311222113311213212322211211131221131211221321123113213221121113122113121113222112131112131221121321131211132221121321132132211331121321232221123113112221131112311322311211131122211213211331121321122112133221121113122113121113222123112221221321132132211231131122211331121321232221121113122113121113222123113221231231121113213221231221132221222112112322211E311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311222112111331121113112221121113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111231133221121113311211131122211211131221131112311332211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213211322111213111213211231131211132211121311222113321132211221121332211S311311222113111231133211121312211231131112311211133112111312211213211312111322211231131122111213122112311311222112111331121113112221121113122113121113222112132113213221232112111312111213322112311311222113111221221113122112132113121113222112311311222113111231133221121113311211131122211211131221131112311332211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211231131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213211322111213111213211231131211132211121311222113321132211221121332211C", Conway.generateList("1A1Z3E1R1T3G1F1D2E1S1C", 20).get(19));
+ }
+
+ @Test
+ public void testGenerateNextElementWith1(){
+ assertEquals("11", Conway.generateNextElement("1"));
+ }
+
+ @Test
+ public void testGenerateNextElementWith123456(){
+ assertEquals("111213141516", Conway.generateNextElement("123456"));
+ }
+
+ @Test
+ public void testGenerateNextElementWith1A1Z3E1R1T3G1F1D2E1S1C(){
+ assertEquals("111A111Z131E111R111T131G111F111D121E111S111C", Conway.generateNextElement("1A1Z3E1R1T3G1F1D2E1S1C"));
+ }
+}
From b14f55096df075bd1cf005c9d40d86e92f8b3ba5 Mon Sep 17 00:00:00 2001
From: YuLuo <1481556636@qq.com>
Date: Sun, 15 Jan 2023 17:28:16 +0800
Subject: [PATCH 0019/1088] Fix LFUCache (#3847)
---
.../datastructures/caches/LFUCache.java | 2 +-
.../datastructures/caches/LFUCacheTest.java | 18 ++++++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java b/src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java
index 01ba5e25005a..de1f6af64de0 100644
--- a/src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java
+++ b/src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java
@@ -101,7 +101,7 @@ private void addNodeWithUpdatedFrequency(Node node) {
node.next = temp;
node.previous = temp.previous;
temp.previous.next = node;
- node.previous = temp.previous;
+ temp.previous = node;
break;
}
} else {
diff --git a/src/test/java/com/thealgorithms/datastructures/caches/LFUCacheTest.java b/src/test/java/com/thealgorithms/datastructures/caches/LFUCacheTest.java
index 14cbb63049f1..6faf6da3a4b4 100644
--- a/src/test/java/com/thealgorithms/datastructures/caches/LFUCacheTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/caches/LFUCacheTest.java
@@ -61,4 +61,22 @@ void testLFUCacheWithStringValueShouldPass() {
assertEquals(null, lfuCache.get(2));
assertEquals("Zeta", lfuCache.get(7));
}
+
+ /**
+ * test addNodeWithUpdatedFrequency method
+ * @author yuluo
+ */
+ @Test
+ void testAddNodeWithUpdatedFrequency() {
+ LFUCache lfuCache = new LFUCache<>(3);
+ lfuCache.put(1, "beijing");
+ lfuCache.put(2, "shanghai");
+ lfuCache.put(3, "gansu");
+
+ assertEquals("beijing", lfuCache.get(1));
+
+ lfuCache.put(1, "shanxi");
+
+ assertEquals("shanxi", lfuCache.get(1));
+ }
}
From 54d6f79acd533721cb43060f476cb9d26b11c37d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hikmet=20=C3=87ak=C4=B1r?=
Date: Tue, 17 Jan 2023 23:05:24 +0300
Subject: [PATCH 0020/1088] Add SimpleSubstitutionCipherTest (#3857)
---
.../ciphers/SimpleSubstitutionCipher.java | 12 -----
.../ciphers/SimpleSubstitutionCipherTest.java | 48 +++++++++++++++++++
2 files changed, 48 insertions(+), 12 deletions(-)
create mode 100644 src/test/java/com/thealgorithms/ciphers/SimpleSubstitutionCipherTest.java
diff --git a/src/main/java/com/thealgorithms/ciphers/SimpleSubstitutionCipher.java b/src/main/java/com/thealgorithms/ciphers/SimpleSubstitutionCipher.java
index 4795638d38f3..6ce3c564abc7 100644
--- a/src/main/java/com/thealgorithms/ciphers/SimpleSubstitutionCipher.java
+++ b/src/main/java/com/thealgorithms/ciphers/SimpleSubstitutionCipher.java
@@ -80,16 +80,4 @@ public static String decode(String encryptedMessage, String cipherSmall) {
return decoded.toString();
}
-
- /**
- * TODO remove main and make JUnit Testing
- */
- public static void main(String[] args) {
- String a = encode(
- "defend the east wall of the castle",
- "phqgiumeaylnofdxjkrcvstzwb"
- );
- String b = decode(a, "phqgiumeaylnofdxjkrcvstzwb");
- System.out.println(b);
- }
}
diff --git a/src/test/java/com/thealgorithms/ciphers/SimpleSubstitutionCipherTest.java b/src/test/java/com/thealgorithms/ciphers/SimpleSubstitutionCipherTest.java
new file mode 100644
index 000000000000..59fb9c072ba5
--- /dev/null
+++ b/src/test/java/com/thealgorithms/ciphers/SimpleSubstitutionCipherTest.java
@@ -0,0 +1,48 @@
+package com.thealgorithms.ciphers;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class SimpleSubstitutionCipherTest {
+
+ @Test
+ void testEncode() {
+ // Given
+ String message = "HELLOWORLD";
+ String key = "phqgiumeaylnofdxjkrcvstzwb";
+
+ // When
+ String actual = SimpleSubstitutionCipher.encode(message, key);
+
+ // Then
+ assertEquals("EINNDTDKNG", actual);
+ }
+
+ @Test
+ void testDecode() {
+ // Given
+ String message = "EINNDTDKNG";
+ String key = "phqgiumeaylnofdxjkrcvstzwb";
+
+ // When
+ String actual = SimpleSubstitutionCipher.decode(message, key);
+
+ // Then
+ assertEquals("HELLOWORLD", actual);
+ }
+
+ @Test
+ void testIsTextTheSameAfterEncodeAndDecode() {
+ // Given
+ String text = "HELLOWORLD";
+ String key = "phqgiumeaylnofdxjkrcvstzwb";
+
+ // When
+ String encodedText = SimpleSubstitutionCipher.encode(text, key);
+ String decodedText = SimpleSubstitutionCipher.decode(encodedText, key);
+
+ // Then
+ assertEquals(text, decodedText);
+ }
+}
From 39df47b5f2e1b5d996fa790447130722c760a21c Mon Sep 17 00:00:00 2001
From: Shivanagouda Agasimani <88313126+shivu2002a@users.noreply.github.com>
Date: Wed, 8 Feb 2023 23:35:52 +0530
Subject: [PATCH 0021/1088] Add Kosaraju Algorithm (#3859)
---
.../datastructures/graphs/Kosaraju.java | 144 ++++++++++++++++++
.../datastructures/graphs/KosarajuTest.java | 81 ++++++++++
2 files changed, 225 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/graphs/Kosaraju.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/graphs/KosarajuTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/Kosaraju.java b/src/main/java/com/thealgorithms/datastructures/graphs/Kosaraju.java
new file mode 100644
index 000000000000..b3632b47970d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/graphs/Kosaraju.java
@@ -0,0 +1,144 @@
+package com.thealgorithms.datastructures.graphs;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * Java program that implements Kosaraju Algorithm.
+ * @author Shivanagouda S A (https://github.com/shivu2002a)
+ *
+ */
+
+/**
+ * Kosaraju algorithm is a linear time algorithm to find the strongly connected components of a
+ directed graph, which, from here onwards will be referred by SCC. It leverages the fact that the transpose
+ graph (same graph with all the edges reversed) has exactly the same SCCs as the original graph.
+
+ * A graph is said to be strongly connected if every vertex is reachable from every other vertex.
+ The SCCs of a directed graph form a partition into subgraphs that are themselves strongly connected.
+ Single node is always a SCC.
+
+ * Example:
+
+ 0 <--- 2 -------> 3 -------- > 4 ---- > 7
+ | ^ | ^ ^
+ | / | \ /
+ | / | \ /
+ v / v \ /
+ 1 5 --> 6
+
+ For the above graph, the SCC list goes as follows:
+ 0, 1, 2
+ 3
+ 4, 5, 6
+ 7
+
+ We can also see that order of the nodes in an SCC doesn't matter since they are in cycle.
+
+ {@summary}
+ * Kosaraju Algorithm:
+ 1. Perform DFS traversal of the graph. Push node to stack before returning. This gives edges sorted by lowest finish time.
+ 2. Find the transpose graph by reversing the edges.
+ 3. Pop nodes one by one from the stack and again to DFS on the modified graph.
+
+ The transpose graph of the above graph:
+ 0 ---> 2 <------- 3 <------- 4 <------ 7
+ ^ / ^ \ /
+ | / | \ /
+ | / | \ /
+ | v | v v
+ 1 5 <--- 6
+
+ We can observe that this graph has the same SCC as that of original graph.
+
+ */
+
+public class Kosaraju {
+
+ // Sort edges according to lowest finish time
+ Stack stack = new Stack();
+
+ //Store each component
+ private List scc = new ArrayList<>();
+
+ //All the strongly connected components
+ private List> sccsList = new ArrayList<>();
+
+ /**
+ *
+ * @param v Node count
+ * @param list Adjacency list of graph
+ * @return List of SCCs
+ */
+ public List> kosaraju(int v, List> list){
+
+ sortEdgesByLowestFinishTime(v, list);
+
+ List> transposeGraph = createTransposeMatrix(v, list);
+
+ findStronglyConnectedComponents(v, transposeGraph);
+
+ return sccsList;
+ }
+
+ private void sortEdgesByLowestFinishTime(int v, List> list){
+ int vis[] = new int[v];
+ for (int i = 0; i < v; i++) {
+ if(vis[i] == 0){
+ dfs(i, vis, list);
+ }
+ }
+ }
+
+ private List> createTransposeMatrix(int v, List> list) {
+ var transposeGraph = new ArrayList>(v);
+ for (int i = 0; i < v; i++) {
+ transposeGraph.add(new ArrayList<>());
+ }
+ for (int i = 0; i < v; i++) {
+ for (Integer neigh : list.get(i)) {
+ transposeGraph.get(neigh).add(i);
+ }
+ }
+ return transposeGraph;
+ }
+
+ /**
+ *
+ * @param v Node count
+ * @param transposeGraph Transpose of the given adjacency list
+ */
+ public void findStronglyConnectedComponents(int v, List> transposeGraph){
+ int vis[] = new int[v];
+ while (!stack.isEmpty()) {
+ var node = stack.pop();
+ if(vis[node] == 0){
+ dfs2(node, vis, transposeGraph);
+ sccsList.add(scc);
+ scc = new ArrayList<>();
+ }
+ }
+ }
+
+ //Dfs to store the nodes in order of lowest finish time
+ private void dfs(int node, int vis[], List> list){
+ vis[node] = 1;
+ for(Integer neighbour : list.get(node)){
+ if(vis[neighbour] == 0)
+ dfs(neighbour, vis, list);
+ }
+ stack.push(node);
+ }
+
+ //Dfs to find all the nodes of each strongly connected component
+ private void dfs2(int node, int vis[], List> list){
+ vis[node] = 1;
+ for(Integer neighbour : list.get(node)){
+ if(vis[neighbour] == 0)
+ dfs2(neighbour, vis, list);
+ }
+ scc.add(node);
+ }
+
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/KosarajuTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/KosarajuTest.java
new file mode 100644
index 000000000000..5395b04ee732
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/graphs/KosarajuTest.java
@@ -0,0 +1,81 @@
+package com.thealgorithms.datastructures.graphs;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+public class KosarajuTest {
+
+ private Kosaraju kosaraju = new Kosaraju();
+
+ @Test
+ public void findStronglyConnectedComps() {
+ //Create a adjacency list of graph
+ var n = 8;
+ var adjList = new ArrayList>(n);
+
+ for (int i = 0; i < n; i++) {
+ adjList.add(new ArrayList<>());
+ }
+
+ adjList.get(0).add(1);
+ adjList.get(1).add(2);
+ adjList.get(2).add(0);
+ adjList.get(2).add(3);
+ adjList.get(3).add(4);
+ adjList.get(4).add(5);
+ adjList.get(4).add(7);
+ adjList.get(5).add(6);
+ adjList.get(6).add(4);
+ adjList.get(6).add(7);
+
+ List> actualResult = kosaraju.kosaraju(n, adjList);
+ List> expectedResult = new ArrayList<>();
+ /*
+ Expected result:
+ 0, 1, 2
+ 3
+ 5, 4, 6
+ 7
+ */
+ expectedResult.add(Arrays.asList(1, 2, 0));
+ expectedResult.add(Arrays.asList(3));
+ expectedResult.add(Arrays.asList(5, 6, 4));
+ expectedResult.add(Arrays.asList(7));
+ assertTrue(expectedResult.equals(actualResult));
+ }
+
+ @Test
+ public void findStronglyConnectedCompsShouldGetSingleNodes() {
+ //Create a adjacency list of graph
+ var n = 8;
+ var adjList = new ArrayList>(n);
+
+ for (int i = 0; i < n; i++) {
+ adjList.add(new ArrayList<>());
+ }
+
+ adjList.get(0).add(1);
+ adjList.get(1).add(2);
+ adjList.get(2).add(3);
+ adjList.get(3).add(4);
+ adjList.get(4).add(5);
+ adjList.get(5).add(6);
+ adjList.get(6).add(7);
+ adjList.get(7).add(0);
+
+ List> actualResult = kosaraju.kosaraju(n, adjList);
+ List> expectedResult = new ArrayList<>();
+ /*
+ Expected result:
+ 0, 1, 2, 3, 4, 5, 6, 7
+ */
+ expectedResult.add(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 0));
+ assertTrue(expectedResult.equals(actualResult));
+ }
+
+}
From c0fec8dfe2c91d4cc9dec3f7f67d0a6fc7826085 Mon Sep 17 00:00:00 2001
From: georgioct <56246719+georgioct@users.noreply.github.com>
Date: Wed, 8 Feb 2023 20:09:38 +0200
Subject: [PATCH 0022/1088] Add Optimal Job Scheduling (#3868)
---
.../OptimalJobScheduling.java | 122 +++++++++++++++++
.../OptimalJobSchedulingTest.java | 128 ++++++++++++++++++
2 files changed, 250 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/dynamicprogramming/OptimalJobScheduling.java
create mode 100644 src/test/java/com/thealgorithms/dynamicprogramming/OptimalJobSchedulingTest.java
diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/OptimalJobScheduling.java b/src/main/java/com/thealgorithms/dynamicprogramming/OptimalJobScheduling.java
new file mode 100644
index 000000000000..071880af5d9d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/dynamicprogramming/OptimalJobScheduling.java
@@ -0,0 +1,122 @@
+package com.thealgorithms.dynamicprogramming;
+
+/**
+ * This class refers to the Optimal Job Scheduling problem with the following constrains:
+ * - precedence relation between the processes
+ * - machine pair dependent transportation delays
+ *
+ * https://en.wikipedia.org/wiki/Optimal_job_scheduling
+ *
+ * @author georgioct@csd.auth.gr
+ */
+public class OptimalJobScheduling {
+
+ private final int numberProcesses;
+ private final int numberMachines;
+ private final int[][] Run;
+ private final int[][] Transfer;
+ private final int[][] Cost;
+
+ /**
+ * Constructor of the class.
+ * @param numberProcesses ,refers to the number of precedent processes(N)
+ * @param numberMachines ,refers to the number of different machines in our disposal(M)
+ * @param Run , N*M matrix refers to the cost of running each process to each machine
+ * @param Transfer ,M*M symmetric matrix refers to the transportation delay for each pair of machines
+ */
+ public OptimalJobScheduling(int numberProcesses, int numberMachines, int[][] Run, int[][] Transfer) {
+ this.numberProcesses = numberProcesses;
+ this.numberMachines = numberMachines;
+ this.Run = Run;
+ this.Transfer = Transfer;
+ this.Cost = new int[numberProcesses][numberMachines];
+ }
+
+ /**
+ * Function which computes the cost of process scheduling to a number of VMs.
+ */
+ public void execute(){
+ this.calculateCost();
+ this.showResults();
+ }
+
+ /**
+ * Function which computes the cost of running each Process to each and every Machine
+ */
+ private void calculateCost(){
+
+ for (int i=0; i < numberProcesses; i++){ //for each Process
+
+ for (int j=0; j < numberMachines; j++) { //for each Machine
+
+ Cost[i][j] = runningCost(i, j);
+ }
+ }
+ }
+
+ /**
+ * Function which returns the minimum cost of running a certain Process to a certain Machine.In order for the Machine to execute the Process ,he requires the output
+ * of the previously executed Process, which may have been executed to the same Machine or some other.If the previous Process has been executed to another Machine,we
+ * have to transfer her result, which means extra cost for transferring the data from one Machine to another(if the previous Process has been executed to the same
+ * Machine, there is no transport cost).
+ *
+ * @param process ,refers to the Process
+ * @param machine ,refers to the Machine
+ * @return the minimum cost of executing the process to the certain machine.
+ */
+ private int runningCost(int process, int machine) {
+
+ if (process==0) //refers to the first process,which does not require for a previous one to have been executed
+ return Run[process][machine];
+ else {
+
+ int[] runningCosts = new int[numberMachines]; //stores the costs of executing our Process depending on the Machine the previous one was executed
+
+ for (int k=0; k < numberMachines; k++) //computes the cost of executing the previous process to each and every Machine
+ runningCosts[k] = Cost[process-1][k] + Transfer[k][machine] + Run[process][machine]; //transferring the result to our Machine and executing the Process to our Machine
+
+ return findMin(runningCosts); //returns the minimum running cost
+ }
+ }
+
+ /**
+ * Function used in order to return the minimum Cost.
+ * @param cost ,an Array of size M which refers to the costs of executing a Process to each Machine
+ * @return the minimum cost
+ */
+ private int findMin(int[] cost) {
+
+ int min=0;
+
+ for (int i=1;i
Date: Tue, 14 Feb 2023 13:33:14 +0300
Subject: [PATCH 0023/1088] Refactor Level Order Traversal (#3869)
---
.../trees/LevelOrderTraversal.java | 76 +++++++------------
.../trees/LevelOrderTraversalHelper.java | 43 +++++++++++
.../trees/LevelOrderTraversalQueue.java | 45 -----------
.../datastructures/trees/ZigzagTraversal.java | 2 +-
.../trees/LevelOrderTraversalTest.java | 54 +++++++++++++
.../trees/VerticalOrderTraversalTest.java | 2 +-
.../trees/ZigzagTraversalTest.java | 30 +++++++-
7 files changed, 154 insertions(+), 98 deletions(-)
create mode 100644 src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalHelper.java
delete mode 100644 src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalQueue.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversal.java b/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversal.java
index 64ce1f4bb6c1..4b86d644e29c 100644
--- a/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversal.java
+++ b/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversal.java
@@ -1,58 +1,38 @@
package com.thealgorithms.datastructures.trees;
-public class LevelOrderTraversal {
-
- class Node {
-
- int data;
- Node left, right;
-
- public Node(int item) {
- data = item;
- left = right = null;
- }
- }
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
- // Root of the Binary Tree
- Node root;
-
- public LevelOrderTraversal(Node root) {
- this.root = root;
- }
-
- /* function to print level order traversal of tree*/
- void printLevelOrder() {
- int h = height(root);
- int i;
- for (i = 1; i <= h; i++) {
- printGivenLevel(root, i);
- }
- }
+public class LevelOrderTraversal {
- /* Compute the "height" of a tree -- the number of
- nodes along the longest path from the root node
- down to the farthest leaf node.*/
- int height(Node root) {
+ static List> traverse(BinaryTree.Node root) {
if (root == null) {
- return 0;
- } else {
- /**
- * Return the height of larger subtree
- */
- return Math.max(height(root.left), height(root.right)) + 1;
+ return List.of();
}
- }
- /* Print nodes at the given level */
- void printGivenLevel(Node root, int level) {
- if (root == null) {
- return;
- }
- if (level == 1) {
- System.out.print(root.data + " ");
- } else if (level > 1) {
- printGivenLevel(root.left, level - 1);
- printGivenLevel(root.right, level - 1);
+ List> result = new ArrayList<>();
+
+ Queue q = new LinkedList<>();
+ q.add(root);
+ while (!q.isEmpty()) {
+ int nodesOnLevel = q.size();
+ List level = new LinkedList<>();
+ for (int i = 0; i < nodesOnLevel; i++) {
+ BinaryTree.Node tempNode = q.poll();
+ level.add(tempNode.data);
+
+ if (tempNode.left != null) {
+ q.add(tempNode.left);
+ }
+
+ if (tempNode.right != null) {
+ q.add(tempNode.right);
+ }
+ }
+ result.add(level);
}
+ return result;
}
}
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalHelper.java b/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalHelper.java
new file mode 100644
index 000000000000..8fa3dc72bb8c
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalHelper.java
@@ -0,0 +1,43 @@
+package com.thealgorithms.datastructures.trees;
+
+public class LevelOrderTraversalHelper {
+ /* function to print level order traversal of tree*/
+ public static void printLevelOrder(BinaryTree.Node root) {
+ if (root == null) {
+ System.out.println("Root node must not be null! Exiting.");
+ return;
+ }
+
+ int h = height(root);
+ int i;
+ for (i = 1; i <= h; i++) {
+ printGivenLevel(root, i);
+ }
+ }
+
+ /* Compute the "height" of a tree -- the number of
+ nodes along the longest path from the root node
+ down to the farthest leaf node.*/
+ private static int height(BinaryTree.Node root) {
+ if (root == null) {
+ return 0;
+ } else {
+ //return the height of larger subtree
+ return Math.max(height(root.left), height(root.right)) + 1;
+ }
+ }
+
+ /* Print nodes at the given level */
+ public static void printGivenLevel(BinaryTree.Node root, int level) {
+ if (root == null) {
+ System.out.println("Root node must not be null! Exiting.");
+ return;
+ }
+ if (level == 1) {
+ System.out.print(root.data + " ");
+ } else if (level > 1) {
+ printGivenLevel(root.left, level - 1);
+ printGivenLevel(root.right, level - 1);
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalQueue.java b/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalQueue.java
deleted file mode 100644
index 65a0d6e10d60..000000000000
--- a/src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalQueue.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.thealgorithms.datastructures.trees;
-
-import java.util.LinkedList;
-import java.util.Queue;
-
-/* Class to print Level Order Traversal */
-public class LevelOrderTraversalQueue {
-
- /* Class to represent Tree node */
- class Node {
-
- int data;
- Node left, right;
-
- public Node(int item) {
- data = item;
- left = null;
- right = null;
- }
- }
-
- /* Given a binary tree. Print its nodes in level order
- using array for implementing queue */
- void printLevelOrder(Node root) {
- Queue queue = new LinkedList();
- queue.add(root);
- while (!queue.isEmpty()) {
- /* poll() removes the present head.
- For more information on poll() visit
- http://www.tutorialspoint.com/java/util/linkedlist_poll.htm */
- Node tempNode = queue.poll();
- System.out.print(tempNode.data + " ");
-
- /*Enqueue left child */
- if (tempNode.left != null) {
- queue.add(tempNode.left);
- }
-
- /*Enqueue right child */
- if (tempNode.right != null) {
- queue.add(tempNode.right);
- }
- }
- }
-}
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/ZigzagTraversal.java b/src/main/java/com/thealgorithms/datastructures/trees/ZigzagTraversal.java
index 9026fdfaa041..7aafcdf83b3d 100644
--- a/src/main/java/com/thealgorithms/datastructures/trees/ZigzagTraversal.java
+++ b/src/main/java/com/thealgorithms/datastructures/trees/ZigzagTraversal.java
@@ -32,7 +32,7 @@
public class ZigzagTraversal {
public static List> traverse(BinaryTree.Node root) {
if (root == null) {
- return new ArrayList<>();
+ return List.of();
}
List> result = new ArrayList<>();
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalTest.java
new file mode 100644
index 000000000000..8b0a6b65b011
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalTest.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.datastructures.trees;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Albina Gimaletdinova on 08/02/2023
+ */
+public class LevelOrderTraversalTest {
+ @Test
+ public void testRootNull() {
+ assertEquals(Collections.emptyList(), LevelOrderTraversal.traverse(null));
+ }
+
+ @Test
+ public void testSingleNodeTree() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{50});
+ assertEquals(List.of(List.of(50)), LevelOrderTraversal.traverse(root));
+ }
+
+ /*
+ 1
+ / \
+ 2 3
+ /\ /\
+ 4 5 6 7
+ */
+ @Test
+ public void testLevelOrderTraversalCompleteTree() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
+ assertEquals(List.of(List.of(1), List.of(2, 3), List.of(4, 5, 6, 7)), LevelOrderTraversal.traverse(root));
+ }
+
+ /*
+ 1
+ / \
+ 2 3
+ /\ /\
+ 4 5 6 7
+ / \
+ 8 9
+ */
+ @Test
+ public void testLevelOrderTraversalDifferentHeight() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(
+ new Integer[]{1, 2, 3, 4, 5, 6, 7, null, null, 8, null, null, 9});
+ assertEquals(List.of(List.of(1), List.of(2, 3), List.of(4, 5, 6, 7), List.of(8, 9)),
+ LevelOrderTraversal.traverse(root));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java
index 42875e4ffa70..74b036d1f23b 100644
--- a/src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java
@@ -40,7 +40,7 @@ public void testVerticalTraversalCompleteTree() {
/ \
2 3
/\ /\
- 4 56 7
+ 4 5 6 7
/ \
8 9
*/
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/ZigzagTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/ZigzagTraversalTest.java
index 11af07c57e0a..6b89fcff7862 100644
--- a/src/test/java/com/thealgorithms/datastructures/trees/ZigzagTraversalTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/trees/ZigzagTraversalTest.java
@@ -22,9 +22,33 @@ public void testSingleNodeTree() {
assertEquals(List.of(List.of(50)), ZigzagTraversal.traverse(root));
}
+ /*
+ 1
+ / \
+ 2 3
+ /\ /\
+ 4 5 6 7
+ */
@Test
- public void testZigzagTraversal() {
- final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{7, 6, 14, 2, 80, 100});
- assertEquals(List.of(List.of(7), List.of(14, 6), List.of(2, 80, 100)), ZigzagTraversal.traverse(root));
+ public void testZigzagTraversalCompleteTree() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
+ assertEquals(List.of(List.of(1), List.of(3, 2), List.of(4, 5, 6, 7)), ZigzagTraversal.traverse(root));
+ }
+
+ /*
+ 1
+ / \
+ 2 3
+ /\ /\
+ 4 5 6 7
+ / \
+ 8 9
+ */
+ @Test
+ public void testZigzagTraversalDifferentHeight() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(
+ new Integer[]{1, 2, 3, 4, 5, 6, 7, null, null, 8, null, null, 9});
+ assertEquals(List.of(List.of(1), List.of(3, 2), List.of(4, 5, 6, 7), List.of(9, 8)),
+ ZigzagTraversal.traverse(root));
}
}
From 69a428470cad55a484efa078c49efc49d412bccd Mon Sep 17 00:00:00 2001
From: Shivanagouda Agasimani <88313126+shivu2002a@users.noreply.github.com>
Date: Thu, 16 Feb 2023 01:57:21 +0530
Subject: [PATCH 0024/1088] Add Tarjans Algorithm (#3874)
---
.../graphs/TarjansAlgorithm.java | 138 ++++++++++++++++++
.../graphs/TarjansAlgorithmTest.java | 72 +++++++++
2 files changed, 210 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithm.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithmTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithm.java b/src/main/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithm.java
new file mode 100644
index 000000000000..18e43c49daf2
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithm.java
@@ -0,0 +1,138 @@
+package com.thealgorithms.datastructures.graphs;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * Java program that implements Tarjan's Algorithm.
+ * @author Shivanagouda S A (https://github.com/shivu2002a)
+ *
+ */
+
+/**
+ * Tarjan's algorithm is a linear time algorithm to find the strongly connected components of a
+ directed graph, which, from here onwards will be referred as SCC.
+
+ * A graph is said to be strongly connected if every vertex is reachable from every other vertex.
+ The SCCs of a directed graph form a partition into subgraphs that are themselves strongly connected.
+ Single node is always a SCC.
+
+ * Example:
+ 0 --------> 1 -------> 3 --------> 4
+ ^ /
+ | /
+ | /
+ | /
+ | /
+ | /
+ | /
+ | /
+ | /
+ | /
+ |V
+ 2
+
+ For the above graph, the SCC list goes as follows:
+ 1, 2, 0
+ 3
+ 4
+
+ We can also see that order of the nodes in an SCC doesn't matter since they are in cycle.
+
+ {@summary}
+ Tarjan's Algorithm:
+ * DFS search produces a DFS tree
+ * Strongly Connected Components form subtrees of the DFS tree.
+ * If we can find the head of these subtrees, we can get all the nodes in that subtree (including the head)
+ and that will be one SCC.
+ * There is no back edge from one SCC to another (here can be cross edges, but they will not be used).
+
+ * Kosaraju Algorithm aims at doing the same but uses two DFS traversalse whereas Tarjanβs algorithm does
+ the same in a single DFS, which leads to much lower constant factors in the latter.
+
+ */
+public class TarjansAlgorithm {
+
+ //Timer for tracking lowtime and insertion time
+ private int Time;
+
+ private List> SCClist = new ArrayList>();
+
+ public List> stronglyConnectedComponents(int V, List> graph) {
+
+ // Initially all vertices as unvisited, insertion and low time are undefined
+
+ // insertionTime:Time when a node is visited 1st time while DFS traversal
+
+ // lowTime: indicates the earliest visited vertex (the vertex with minimum insertion time) that can
+ // be reached from a subtree rooted with a particular node.
+ int lowTime[] = new int[V];
+ int insertionTime[] = new int[V];
+ for (int i = 0; i < V; i++) {
+ insertionTime[i] = -1;
+ lowTime[i] = -1;
+ }
+
+ // To check if element is present in stack
+ boolean isInStack[] = new boolean[V];
+
+ // Store nodes during DFS
+ Stack st = new Stack();
+
+ for (int i = 0; i < V; i++) {
+ if (insertionTime[i] == -1)
+ stronglyConnCompsUtil(i, lowTime, insertionTime, isInStack, st, graph);
+ }
+
+ return SCClist;
+ }
+
+ private void stronglyConnCompsUtil(int u, int lowTime[], int insertionTime[],
+ boolean isInStack[], Stack st, List> graph) {
+
+ // Initialize insertion time and lowTime value of current node
+ insertionTime[u] = Time;
+ lowTime[u] = Time;
+ Time += 1;
+
+ //Push current node into stack
+ isInStack[u] = true;
+ st.push(u);
+
+ int n;
+
+ // Go through all vertices adjacent to this
+ Iterator i = graph.get(u).iterator();
+
+ while (i.hasNext()) {
+ n = i.next();
+
+ //If the adjacent node is unvisited, do DFS
+ if (insertionTime[n] == -1) {
+ stronglyConnCompsUtil(n, lowTime, insertionTime, isInStack, st, graph);
+ //update lowTime for the current node comparing lowtime of adj node
+ lowTime[u] = Math.min(lowTime[u], lowTime[n]);
+ } else if (isInStack[n] == true) {
+ //If adj node is in stack, update low
+ lowTime[u] = Math.min(lowTime[u], insertionTime[n]);
+ }
+ }
+ //If lowtime and insertion time are same, current node is the head of an SCC
+ // head node found, get all the nodes in this SCC
+ if (lowTime[u] == insertionTime[u]) {
+ int w = -1;
+ var scc = new ArrayList();
+
+ //Stack has all the nodes of the current SCC
+ while (w != u) {
+ w = st.pop();
+ scc.add(w);
+ isInStack[w] = false;
+ }
+ SCClist.add(scc);
+ }
+ }
+
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithmTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithmTest.java
new file mode 100644
index 000000000000..2166b2ef6c68
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithmTest.java
@@ -0,0 +1,72 @@
+package com.thealgorithms.datastructures.graphs;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+public class TarjansAlgorithmTest {
+
+ TarjansAlgorithm tarjansAlgo = new TarjansAlgorithm();
+
+ @Test
+ public void findStronglyConnectedComps(){
+ var v = 5;
+ var graph = new ArrayList>();
+ for (int i = 0; i < v; i++) {
+ graph.add(new ArrayList<>());
+ }
+ graph.get(0).add(1);
+ graph.get(1).add(2);
+ graph.get(2).add(0);
+ graph.get(1).add(3);
+ graph.get(3).add(4);
+
+ var actualResult = tarjansAlgo.stronglyConnectedComponents(v, graph);
+ /*
+ Expected result:
+ 0, 1, 2
+ 3
+ 4
+ */
+ List> expectedResult = new ArrayList<>();
+
+ expectedResult.add(Arrays.asList(4));
+ expectedResult.add(Arrays.asList(3));
+ expectedResult.add(Arrays.asList(2, 1, 0));
+ assertTrue(expectedResult.equals(actualResult));
+ }
+
+ @Test
+ public void findStronglyConnectedCompsShouldGetSingleNodes() {
+ //Create a adjacency list of graph
+ var n = 8;
+ var adjList = new ArrayList>(n);
+
+ for (int i = 0; i < n; i++) {
+ adjList.add(new ArrayList<>());
+ }
+
+ adjList.get(0).add(1);
+ adjList.get(1).add(2);
+ adjList.get(2).add(3);
+ adjList.get(3).add(4);
+ adjList.get(4).add(5);
+ adjList.get(5).add(6);
+ adjList.get(6).add(7);
+ adjList.get(7).add(0);
+
+ List> actualResult = tarjansAlgo.stronglyConnectedComponents(n, adjList);
+ List> expectedResult = new ArrayList<>();
+ /*
+ Expected result:
+ 7, 6, 5, 4, 3, 2, 1, 0
+ */
+ expectedResult.add(Arrays.asList(7, 6, 5, 4, 3, 2, 1, 0));
+ assertTrue(expectedResult.equals(actualResult));
+ }
+
+}
From e0b1235befa3f1b846c6b1c52f9f9fcced96020f Mon Sep 17 00:00:00 2001
From: Davide Nigri <30591411+davnig@users.noreply.github.com>
Date: Wed, 15 Feb 2023 21:34:36 +0100
Subject: [PATCH 0025/1088] Fix ArrayIndexOutOfBoundsException in
LevenshteinDistance (#3871)
---
.../LevenshteinDistance.java | 49 +++++++++----------
.../LevenshteinDistanceTests.java | 17 +++++++
2 files changed, 40 insertions(+), 26 deletions(-)
create mode 100644 src/test/java/com/thealgorithms/dynamicprogramming/LevenshteinDistanceTests.java
diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/LevenshteinDistance.java b/src/main/java/com/thealgorithms/dynamicprogramming/LevenshteinDistance.java
index e3e221ea7aa9..f2a96187bc91 100644
--- a/src/main/java/com/thealgorithms/dynamicprogramming/LevenshteinDistance.java
+++ b/src/main/java/com/thealgorithms/dynamicprogramming/LevenshteinDistance.java
@@ -17,43 +17,40 @@ private static int minimum(int a, int b, int c) {
}
}
- private static int calculate_distance(String a, String b) {
- int len_a = a.length() + 1;
- int len_b = b.length() + 1;
- int[][] distance_mat = new int[len_a][len_b];
- for (int i = 0; i < len_a; i++) {
- distance_mat[i][0] = i;
+ public static int calculateLevenshteinDistance(String str1, String str2) {
+ int len1 = str1.length() + 1;
+ int len2 = str2.length() + 1;
+ int[][] distanceMat = new int[len1][len2];
+ for (int i = 0; i < len1; i++) {
+ distanceMat[i][0] = i;
}
- for (int j = 0; j < len_b; j++) {
- distance_mat[0][j] = j;
+ for (int j = 0; j < len2; j++) {
+ distanceMat[0][j] = j;
}
- for (int i = 0; i < len_a; i++) {
- for (int j = 0; j < len_b; j++) {
- int cost;
- if (a.charAt(i) == b.charAt(j)) {
- cost = 0;
+ for (int i = 1; i < len1; i++) {
+ for (int j = 1; j < len2; j++) {
+ if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
+ distanceMat[i][j] = distanceMat[i - 1][j - 1];
} else {
- cost = 1;
+ distanceMat[i][j] =
+ 1 + minimum(
+ distanceMat[i - 1][j],
+ distanceMat[i - 1][j - 1],
+ distanceMat[i][j - 1]
+ );
}
- distance_mat[i][j] =
- minimum(
- distance_mat[i - 1][j],
- distance_mat[i - 1][j - 1],
- distance_mat[i][j - 1]
- ) +
- cost;
}
}
- return distance_mat[len_a - 1][len_b - 1];
+ return distanceMat[len1 - 1][len2 - 1];
}
public static void main(String[] args) {
- String a = ""; // enter your string here
- String b = ""; // enter your string here
+ String str1 = ""; // enter your string here
+ String str2 = ""; // enter your string here
System.out.print(
- "Levenshtein distance between " + a + " and " + b + " is: "
+ "Levenshtein distance between " + str1 + " and " + str2 + " is: "
);
- System.out.println(calculate_distance(a, b));
+ System.out.println(calculateLevenshteinDistance(str1, str2));
}
}
diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/LevenshteinDistanceTests.java b/src/test/java/com/thealgorithms/dynamicprogramming/LevenshteinDistanceTests.java
new file mode 100644
index 000000000000..4e3cfa3c4b7d
--- /dev/null
+++ b/src/test/java/com/thealgorithms/dynamicprogramming/LevenshteinDistanceTests.java
@@ -0,0 +1,17 @@
+package com.thealgorithms.dynamicprogramming;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class LevenshteinDistanceTests {
+
+ @ParameterizedTest
+ @CsvSource({"dog,cat,3", "sunday,saturday,3", "cat,cats,1", "rain,train,1"})
+ void levenshteinDistanceTest(String str1, String str2, int distance) {
+ int result = LevenshteinDistance.calculateLevenshteinDistance(str1, str2);
+ assertEquals(distance, result);
+ }
+
+}
From d565edc69abbd5ac44e80cabed36f7d4f2a158d5 Mon Sep 17 00:00:00 2001
From: Albina Gimaletdinova
Date: Fri, 17 Feb 2023 14:34:44 +0300
Subject: [PATCH 0026/1088] Added recursive&iterative preorder binary tree
traversal (#3884)
Added recursive& iterative preorder binary tree traversal
---
.../trees/PreOrderTraversal.java | 59 +++++++++++++++++++
.../trees/PreOrderTraversalTest.java | 49 +++++++++++++++
2 files changed, 108 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/trees/PreOrderTraversal.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/PreOrderTraversal.java b/src/main/java/com/thealgorithms/datastructures/trees/PreOrderTraversal.java
new file mode 100644
index 000000000000..d0a5bc4ac3f0
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/trees/PreOrderTraversal.java
@@ -0,0 +1,59 @@
+package com.thealgorithms.datastructures.trees;
+
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Given tree is traversed in a 'pre-order' way: ROOT -> LEFT -> RIGHT.
+ * Below are given the recursive and iterative implementations.
+ *
+ * Complexities:
+ * Recursive: O(n) - time, O(n) - space, where 'n' is the number of nodes in a tree.
+ *
+ * Iterative: O(n) - time, O(h) - space, where 'n' is the number of nodes in a tree
+ * and 'h' is the height of a binary tree.
+ * In the worst case 'h' can be O(n) if tree is completely unbalanced, for instance:
+ * 5
+ * \
+ * 6
+ * \
+ * 7
+ * \
+ * 8
+ *
+ * @author Albina Gimaletdinova on 17/02/2023
+ */
+public class PreOrderTraversal {
+ public static List recursivePreOrder(BinaryTree.Node root) {
+ List result = new ArrayList<>();
+ recursivePreOrder(root, result);
+ return result;
+ }
+
+ public static List iterativePreOrder(BinaryTree.Node root) {
+ List result = new ArrayList<>();
+ if (root == null) return result;
+
+ Deque stack = new LinkedList<>();
+ stack.push(root);
+ while (!stack.isEmpty()) {
+ BinaryTree.Node node = stack.pop();
+ result.add(node.data);
+ if (node.right != null) stack.push(node.right);
+ if (node.left != null) stack.push(node.left);
+ }
+
+ return result;
+ }
+
+ private static void recursivePreOrder(BinaryTree.Node root, List result) {
+ if (root == null) {
+ return;
+ }
+ result.add(root.data);
+ recursivePreOrder(root.left, result);
+ recursivePreOrder(root.right, result);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java
new file mode 100644
index 000000000000..eeac2131a78b
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java
@@ -0,0 +1,49 @@
+package com.thealgorithms.datastructures.trees;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Albina Gimaletdinova on 17/02/2023
+ */
+public class PreOrderTraversalTest {
+ @Test
+ public void testNullRoot() {
+ assertEquals(Collections.emptyList(), PreOrderTraversal.recursivePreOrder(null));
+ assertEquals(Collections.emptyList(), PreOrderTraversal.iterativePreOrder(null));
+ }
+
+ /*
+ 1
+ / \
+ 2 3
+ /\ /\
+ 4 5 6 7
+ */
+ @Test
+ public void testRecursivePreOrder() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
+ assertEquals(List.of(1, 2, 4, 5, 3, 6, 7), PreOrderTraversal.recursivePreOrder(root));
+ assertEquals(List.of(1, 2, 4, 5, 3, 6, 7), PreOrderTraversal.iterativePreOrder(root));
+ }
+
+ /*
+ 5
+ \
+ 6
+ \
+ 7
+ \
+ 8
+ */
+ @Test
+ public void testRecursivePreOrderNonBalanced() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{5, null, 6, null, 7, null, 8});
+ assertEquals(List.of(5, 6, 7, 8), PreOrderTraversal.recursivePreOrder(root));
+ assertEquals(List.of(5, 6, 7, 8), PreOrderTraversal.iterativePreOrder(root));
+ }
+}
From 541f490d1eef4a1b9ff5e269116c77324f4ce098 Mon Sep 17 00:00:00 2001
From: Albina Gimaletdinova
Date: Fri, 17 Feb 2023 14:43:17 +0300
Subject: [PATCH 0027/1088] Valid BST: refactoring + added unit test (#3883)
Co-authored-by: Debasish Biswas
---
.../datastructures/trees/ValidBSTOrNot.java | 39 ++++--------
.../trees/ValidBSTOrNotTest.java | 61 +++++++++++++++++++
2 files changed, 72 insertions(+), 28 deletions(-)
create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/ValidBSTOrNotTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/ValidBSTOrNot.java b/src/main/java/com/thealgorithms/datastructures/trees/ValidBSTOrNot.java
index 395a9ea30dcf..65c4e1070da7 100644
--- a/src/main/java/com/thealgorithms/datastructures/trees/ValidBSTOrNot.java
+++ b/src/main/java/com/thealgorithms/datastructures/trees/ValidBSTOrNot.java
@@ -1,45 +1,28 @@
package com.thealgorithms.datastructures.trees;
+/**
+ * This code recursively validates whether given Binary Search Tree (BST) is balanced or not.
+ * Trees with only distinct values are supported.
+ * Key points:
+ * 1. According to the definition of a BST, each node in a tree must be in range [min, max],
+ * where 'min' and 'max' values represent the child nodes (left, right).
+ * 2. The smallest possible node value is Integer.MIN_VALUE, the biggest - Integer.MAX_VALUE.
+ */
public class ValidBSTOrNot {
-
- class Node {
-
- int data;
- Node left, right;
-
- public Node(int item) {
- data = item;
- left = right = null;
- }
- }
-
- // Root of the Binary Tree
-
- /* can give min and max value according to your code or
- can write a function to find min and max value of tree. */
-
- /* returns true if given search tree is binary
- search tree (efficient version) */
- boolean isBST(Node root) {
+ public static boolean isBST(BinaryTree.Node root) {
return isBSTUtil(root, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
- /* Returns true if the given tree is a BST and its
- values are >= min and <= max. */
- boolean isBSTUtil(Node node, int min, int max) {
- /* an empty tree is BST */
+ private static boolean isBSTUtil(BinaryTree.Node node, int min, int max) {
+ // empty tree is a BST
if (node == null) {
return true;
}
- /* false if this node violates the min/max constraints */
if (node.data < min || node.data > max) {
return false;
}
- /* otherwise check the subtrees recursively
- tightening the min/max constraints */
- // Allow only distinct values
return (
isBSTUtil(node.left, min, node.data - 1) &&
isBSTUtil(node.right, node.data + 1, max)
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/ValidBSTOrNotTest.java b/src/test/java/com/thealgorithms/datastructures/trees/ValidBSTOrNotTest.java
new file mode 100644
index 000000000000..b3189a805dbe
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/ValidBSTOrNotTest.java
@@ -0,0 +1,61 @@
+package com.thealgorithms.datastructures.trees;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author Albina Gimaletdinova on 17/02/2023
+ */
+public class ValidBSTOrNotTest {
+ @Test
+ public void testRootNull() {
+ assertTrue(ValidBSTOrNot.isBST(null));
+ }
+
+ @Test
+ public void testOneNode() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{Integer.MIN_VALUE});
+ assertTrue(ValidBSTOrNot.isBST(root));
+ }
+
+ /*
+ 9
+ / \
+ 7 13
+ /\ / \
+ 3 8 10 20
+ */
+ @Test
+ public void testBinaryTreeIsBST() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{9, 7, 13, 3, 8, 10, 20});
+ assertTrue(ValidBSTOrNot.isBST(root));
+ }
+
+ /*
+ 9
+ / \
+ 7 13
+ /\ / \
+ 3 8 10 13 <--- duplicated node
+ */
+ @Test
+ public void testBinaryTreeWithDuplicatedNodesIsNotBST() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{9, 7, 13, 3, 8, 10, 13});
+ assertFalse(ValidBSTOrNot.isBST(root));
+ }
+
+ /*
+ 9
+ / \
+ 7 13
+ /\ / \
+ 3 8 10 12 <---- violates BST rule, needs to be more than 13 (parent node)
+ */
+ @Test
+ public void testBinaryTreeIsNotBST() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{9, 7, 13, 3, 8, 10, 12});
+ assertFalse(ValidBSTOrNot.isBST(root));
+ }
+}
From 3c0d94292cdb94c1719bf8d93398233f2797df03 Mon Sep 17 00:00:00 2001
From: Specialist Steak <102715674+SpecialistSteak@users.noreply.github.com>
Date: Mon, 20 Feb 2023 01:20:59 +0530
Subject: [PATCH 0028/1088] Add Introspective Search (#3887)
---
.../sorts/IntrospectiveSort.java | 90 +++++++++++++++++++
.../sorts/IntrospectiveSortTest.java | 65 ++++++++++++++
2 files changed, 155 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/sorts/IntrospectiveSort.java
create mode 100644 src/test/java/com/thealgorithms/sorts/IntrospectiveSortTest.java
diff --git a/src/main/java/com/thealgorithms/sorts/IntrospectiveSort.java b/src/main/java/com/thealgorithms/sorts/IntrospectiveSort.java
new file mode 100644
index 000000000000..930bb02c7ce7
--- /dev/null
+++ b/src/main/java/com/thealgorithms/sorts/IntrospectiveSort.java
@@ -0,0 +1,90 @@
+package com.thealgorithms.sorts;
+
+/**
+ * Introspective Sort Algorithm Implementation
+ *
+ * @see IntroSort Algorithm
+ */
+public class IntrospectiveSort implements SortAlgorithm {
+
+ private static final int INSERTION_SORT_THRESHOLD = 16;
+
+ @Override
+ public > T[] sort(T[] a) {
+ int n = a.length;
+ introSort(a, 0, n - 1, 2 * (int) (Math.log(n) / Math.log(2)));
+ return a;
+ }
+
+ private static > void swap(T[] a, int i, int j) {
+ T temp = a[i];
+ a[i] = a[j];
+ a[j] = temp;
+ }
+
+ private static > void introSort(T[] a, int low, int high, int depth) {
+ while (high - low > INSERTION_SORT_THRESHOLD) {
+ if (depth == 0) {
+ heapSort(a, low, high);
+ return;
+ }
+ int pivotIndex = partition(a, low, high);
+ introSort(a, pivotIndex + 1, high, depth - 1);
+ high = pivotIndex - 1;
+ }
+ insertionSort(a, low, high);
+ }
+
+ private static > int partition(T[] a, int low, int high) {
+ int pivotIndex = low + (int) (Math.random() * (high - low + 1));
+ swap(a, pivotIndex, high);
+ T pivot = a[high];
+ int i = low - 1;
+ for (int j = low; j <= high - 1; j++) {
+ if (a[j].compareTo(pivot) <= 0) {
+ i++;
+ swap(a, i, j);
+ }
+ }
+ swap(a, i + 1, high);
+ return i + 1;
+ }
+
+ private static > void insertionSort(T[] a, int low, int high) {
+ for (int i = low + 1; i <= high; i++) {
+ T key = a[i];
+ int j = i - 1;
+ while (j >= low && a[j].compareTo(key) > 0) {
+ a[j + 1] = a[j];
+ j--;
+ }
+ a[j + 1] = key;
+ }
+ }
+
+ private static > void heapSort(T[] a, int low, int high) {
+ for (int i = (high + low - 1) / 2; i >= low; i--) {
+ heapify(a, i, high - low + 1, low);
+ }
+ for (int i = high; i > low; i--) {
+ swap(a, low, i);
+ heapify(a, low, i - low, low);
+ }
+ }
+
+ private static > void heapify(T[] a, int i, int n, int low) {
+ int left = 2 * i - low + 1;
+ int right = 2 * i - low + 2;
+ int largest = i;
+ if (left < n && a[left].compareTo(a[largest]) > 0) {
+ largest = left;
+ }
+ if (right < n && a[right].compareTo(a[largest]) > 0) {
+ largest = right;
+ }
+ if (largest != i) {
+ swap(a, i, largest);
+ heapify(a, largest, n, low);
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/sorts/IntrospectiveSortTest.java b/src/test/java/com/thealgorithms/sorts/IntrospectiveSortTest.java
new file mode 100644
index 000000000000..caaf3f4b5914
--- /dev/null
+++ b/src/test/java/com/thealgorithms/sorts/IntrospectiveSortTest.java
@@ -0,0 +1,65 @@
+package com.thealgorithms.sorts;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class IntrospectiveSortTest {
+ @Test
+ // valid test case
+ public void StrandSortNonDuplicateTest() {
+ Integer[] expectedArray = {1, 2, 3, 4, 5};
+ Integer[] actualList = new IntrospectiveSort().sort(expectedArray);
+ assertArrayEquals(expectedArray, actualList);
+ }
+
+ @Test
+ // valid test case
+ public void StrandSortDuplicateTest() {
+ Integer[] expectedArray = {2, 2, 2, 5, 7};
+ Integer[] actualList = new IntrospectiveSort().sort(expectedArray);
+ assertArrayEquals(expectedArray, actualList);
+ }
+
+ @Test
+ // valid test case
+ public void StrandSortEmptyTest() {
+ Integer[] expectedArray = {};
+ Integer[] actualList = new IntrospectiveSort().sort(expectedArray);
+ assertArrayEquals(expectedArray, actualList);
+ }
+
+ @Test
+ // valid test case
+ public void StrandSortNullTest() {
+ Integer[] expectedArray = null;
+ assertThrows(NullPointerException.class, () -> {
+ new IntrospectiveSort().sort(expectedArray);
+ });
+ }
+
+ @Test
+ // valid test case
+ public void StrandSortNegativeTest() {
+ Integer[] expectedArray = {-1, -2, -3, -4, -5};
+ Integer[] actualList = new IntrospectiveSort().sort(expectedArray);
+ assertArrayEquals(expectedArray, actualList);
+ }
+
+ @Test
+ // valid test case
+ public void StrandSortNegativeAndPositiveTest() {
+ Integer[] expectedArray = {-1, -2, -3, 4, 5};
+ Integer[] actualList = new IntrospectiveSort().sort(expectedArray);
+ assertArrayEquals(expectedArray, actualList);
+ }
+
+ @Test
+ // valid test case
+ public void allSameTest() {
+ Integer[] expectedArray = {1, 1, 1, 1, 1};
+ Integer[] actualList = new IntrospectiveSort().sort(expectedArray);
+ assertArrayEquals(expectedArray, actualList);
+ }
+}
From 6b9eb1b9c1eddd1615a1d00d99d3e1c7f77fdbac Mon Sep 17 00:00:00 2001
From: HumbleFool <111487330+HumbleFool830@users.noreply.github.com>
Date: Thu, 23 Feb 2023 22:49:05 +0530
Subject: [PATCH 0029/1088] Add orderAgnosticBinarySearch (#3882)
Co-authored-by: Andrii Siriak
---
.../sortOrderAgnosticBinarySearch.java | 32 +++++++++++++++++++
.../sortOrderAgnosticBinarySearchTest.java | 27 ++++++++++++++++
2 files changed, 59 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/searches/sortOrderAgnosticBinarySearch.java
create mode 100644 src/test/java/com/thealgorithms/searches/sortOrderAgnosticBinarySearchTest.java
diff --git a/src/main/java/com/thealgorithms/searches/sortOrderAgnosticBinarySearch.java b/src/main/java/com/thealgorithms/searches/sortOrderAgnosticBinarySearch.java
new file mode 100644
index 000000000000..9f60b31b603b
--- /dev/null
+++ b/src/main/java/com/thealgorithms/searches/sortOrderAgnosticBinarySearch.java
@@ -0,0 +1,32 @@
+package com.thealgorithms.searches;
+import java.util.*;
+public class 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(keyarr[mid]){
+ start=mid+1;
+ }
+ else{
+ end=mid-1;
+ }
+ }
+ }
+ return -1;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/searches/sortOrderAgnosticBinarySearchTest.java b/src/test/java/com/thealgorithms/searches/sortOrderAgnosticBinarySearchTest.java
new file mode 100644
index 000000000000..37f1aa403dcb
--- /dev/null
+++ b/src/test/java/com/thealgorithms/searches/sortOrderAgnosticBinarySearchTest.java
@@ -0,0 +1,27 @@
+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 );
+ }
+
+}
\ No newline at end of file
From be13981e94f8a18a194d8eb9a2f8b8483e1fbcda Mon Sep 17 00:00:00 2001
From: Isak Einberg <45336755+einbergisak@users.noreply.github.com>
Date: Thu, 23 Feb 2023 19:49:24 +0100
Subject: [PATCH 0030/1088] Add tests for 2D array binary search (#3892)
---
.../searches/BinarySearch2dArrayTest.java | 66 +++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java b/src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java
index ace42b8e03a2..0db17bdb2406 100644
--- a/src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java
+++ b/src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java
@@ -1,9 +1,12 @@
package com.thealgorithms.searches;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.*;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.AfterAll;
+
public class BinarySearch2dArrayTest {
@@ -97,4 +100,67 @@ public void BinarySearch2dArrayTestNotFound() {
assertEquals(-1, ans[0]);
assertEquals(-1, ans[1]);
}
+
+ /**
+ * Test if the method works with input arrays consisting only of one row.
+ */
+ @Test
+ public void BinarySearch2dArrayTestOneRow() {
+ int[][] arr = { { 1, 2, 3, 4 }};
+ int target = 2;
+
+ // Assert that the requirement, that the array only has one row, is fulfilled.
+ assertEquals(arr.length, 1);
+ int[] ans = BinarySearch2dArray.BinarySearch(arr, target);
+ System.out.println(Arrays.toString(ans));
+ assertEquals(0, ans[0]);
+ assertEquals(1, ans[1]);
+ }
+
+ /**
+ * Test if the method works with the target in the middle of the input.
+ */
+ @Test
+ public void BinarySearch2dArrayTestTargetInMiddle() {
+ int[][] arr = { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10 }, { 11, 12, 13, 14, 15} };
+ 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);
+ int[] ans = BinarySearch2dArray.BinarySearch(arr, target);
+ System.out.println(Arrays.toString(ans));
+ assertEquals(1, ans[0]);
+ assertEquals(2, ans[1]);
+ }
+
+ /**
+ * Test if the method works with the target in the middle column,
+ * in the row above the middle row.
+ */
+ @Test
+ public void BinarySearch2dArrayTestTargetAboveMiddleRowInMiddleColumn() {
+ int[][] arr = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
+ int target = 3;
+
+ // 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);
+ int[] ans = BinarySearch2dArray.BinarySearch(arr, target);
+ System.out.println(Arrays.toString(ans));
+ assertEquals(0, ans[0]);
+ assertEquals(2, ans[1]);
+ }
+
+ /**
+ * Test if the method works with an empty array.
+ */
+ @Test
+ public void BinarySearch2dArrayTestEmptyArray() {
+ int[][] arr = {};
+ int target = 5;
+
+ // Assert that an empty array is not valid input for the method.
+ assertThrows(ArrayIndexOutOfBoundsException.class, () -> BinarySearch2dArray.BinarySearch(arr, target));
+ }
+
}
From 6d13d95e416e2dfb4c08d3e5b823e26c9f10266d Mon Sep 17 00:00:00 2001
From: Stronshade <82626532+Stronshade@users.noreply.github.com>
Date: Sat, 25 Feb 2023 07:01:51 -0600
Subject: [PATCH 0031/1088] Graham scan algorithm (#3903)
* Added Graham scan algorithm #3894
* Added Graham scan algorithm (#3894)
---------
Co-authored-by: Stronshade
---
.../thealgorithms/geometry/GrahamScan.java | 155 ++++++++++++++++++
.../geometry/GrahamScanTest.java | 19 +++
2 files changed, 174 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/geometry/GrahamScan.java
create mode 100644 src/test/java/com/thealgorithms/geometry/GrahamScanTest.java
diff --git a/src/main/java/com/thealgorithms/geometry/GrahamScan.java b/src/main/java/com/thealgorithms/geometry/GrahamScan.java
new file mode 100644
index 000000000000..9b527597100e
--- /dev/null
+++ b/src/main/java/com/thealgorithms/geometry/GrahamScan.java
@@ -0,0 +1,155 @@
+package com.thealgorithms.geometry;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Stack;
+
+/*
+ * A Java program that computes the convex hull using the Graham Scan algorithm
+ * In the best case, time complexity is O(n), while in the worst case, it is log(n).
+ * O(n) space complexity
+ *
+ * This algorithm is only applicable to integral coordinates.
+ *
+ * Reference:
+ * https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/graham_scan_algorithm.cpp
+ * https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/graham_scan_functions.hpp
+ * https://algs4.cs.princeton.edu/99hull/GrahamScan.java.html
+ */
+public class GrahamScan {
+ private final Stack hull = new Stack<>();
+
+ public GrahamScan(Point[] points) {
+
+ /*
+ * pre-process the points by sorting them with respect to the bottom-most point, then we'll push the
+ * first point in the array to be our first extreme point.
+ */
+ Arrays.sort(points);
+ Arrays.sort(points, 1, points.length, points[0].polarOrder());
+ hull.push(points[0]);
+
+ // find index of first point not equal to a[0] (indexPoint1) and the first point that's not
+ // collinear with either (indexPoint2).
+ int indexPoint1;
+ for (indexPoint1 = 1; indexPoint1 < points.length; indexPoint1++)
+ if (!points[0].equals(points[indexPoint1])) break;
+ if (indexPoint1 == points.length) return;
+
+ int indexPoint2;
+ for (indexPoint2 = indexPoint1+1; indexPoint2 < points.length; indexPoint2++)
+ if (Point.orientation(points[0], points[indexPoint1], points[indexPoint2]) != 0) break;
+ hull.push(points[indexPoint2-1]);
+
+ // Now we simply add the point to the stack based on the orientation.
+ for (int i = indexPoint2; i < points.length; i++) {
+ Point top = hull.pop();
+ while (Point.orientation(hull.peek(), top, points[i]) <= 0) {
+ top = hull.pop();
+ }
+ hull.push(top);
+ hull.push(points[i]);
+ }
+ }
+
+ /**
+ * @return A stack of points representing the convex hull.
+ */
+ public Iterable hull() {
+ Stack s = new Stack<>();
+ for (Point p : hull) s.push(p);
+ return s;
+ }
+
+ public record Point(int x, int y) implements Comparable {
+
+ /**
+ * Default constructor
+ * @param x x-coordinate
+ * @param y y-coordinate
+ */
+ public Point { }
+
+ /**
+ * @return the x-coordinate
+ */
+ @Override
+ public int x() {
+ return x;
+ }
+
+ /**
+ * @return the y-coordinate
+ */
+ @Override
+ public int y() { return y; }
+
+ /**
+ * Finds the orientation of ordered triplet.
+ *
+ * @param a Co-ordinates of point a
+ * @param b Co-ordinates of point a
+ * @param c Co-ordinates of point a
+ * @return { -1, 0, +1 } if a -β b -β c is a { clockwise, collinear; counterclockwise } turn.
+ */
+ public static int orientation(Point a, Point b, Point c) {
+ int val = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
+ if (val == 0) {
+ return 0;
+ }
+ return (val > 0) ? +1 : -1;
+ }
+
+ /**
+ * @param p2 Co-ordinate of point to compare to.
+ * This function will compare the points and will return a positive integer it the
+ * point is greater than the argument point and a negative integer if the point is
+ * less than the argument point.
+ */
+ public int compareTo(Point p2) {
+ if (this.y < p2.y) return -1;
+ if (this.y > p2.y) return +1;
+ if (this.x < p2.x) return -1;
+ if (this.x > p2.x) return +1;
+ return 0;
+ }
+
+ /**
+ * A helper function that will let us sort points by their polar order
+ * This function will compare the angle between 2 polar Co-ordinates
+ *
+ * @return the comparator
+ */
+ public Comparator polarOrder() {
+ return new PolarOrder();
+ }
+
+ private class PolarOrder implements Comparator {
+ public int compare(Point p1, Point p2) {
+ int dx1 = p1.x - x;
+ int dy1 = p1.y - y;
+ int dx2 = p2.x - x;
+ int dy2 = p2.y - y;
+
+ if (dy1 >= 0 && dy2 < 0) return -1; // q1 above; q2 below
+ else if (dy2 >= 0 && dy1 < 0) return +1; // q1 below; q2 above
+ else if (dy1 == 0 && dy2 == 0) { // 3-collinear and horizontal
+ if (dx1 >= 0 && dx2 < 0) return -1;
+ else if (dx2 >= 0 && dx1 < 0) return +1;
+ else return 0;
+ } else return -orientation(Point.this, p1, p2); // both above or below
+ }
+ }
+
+ /**
+ * Override of the toString method, necessary to compute the difference
+ * between the expected result and the derived result
+ *
+ * @return a string representation of any given 2D point in the format (x, y)
+ */
+ @Override
+ public String toString() {
+ return "(" + x + ", " + y + ")";
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/geometry/GrahamScanTest.java b/src/test/java/com/thealgorithms/geometry/GrahamScanTest.java
new file mode 100644
index 000000000000..c31802f9b31a
--- /dev/null
+++ b/src/test/java/com/thealgorithms/geometry/GrahamScanTest.java
@@ -0,0 +1,19 @@
+package com.thealgorithms.geometry;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class GrahamScanTest {
+ @Test
+ void testGrahamScan() {
+ GrahamScan.Point[] points = {new GrahamScan.Point(0, 3), new GrahamScan.Point(1, 1),
+ new GrahamScan.Point(2, 2), new GrahamScan.Point(4, 4),
+ new GrahamScan.Point(0, 0), new GrahamScan.Point(1, 2),
+ new GrahamScan.Point(3, 1), new GrahamScan.Point(3, 3)};
+ String expectedResult = "[(0, 0), (3, 1), (4, 4), (0, 3)]";
+
+ GrahamScan graham = new GrahamScan(points);
+ assertEquals(expectedResult, graham.hull().toString());
+ }
+}
\ No newline at end of file
From 45923d68726e111fd1663ca7975c09b764cdbd34 Mon Sep 17 00:00:00 2001
From: Albina Gimaletdinova
Date: Sat, 25 Feb 2023 23:58:06 +0300
Subject: [PATCH 0032/1088] Add inorder binary tree traversal (#3898)
---
.../trees/InorderTraversal.java | 60 +++++++++++++++++++
.../trees/InorderTraversalTest.java | 53 ++++++++++++++++
.../trees/PreOrderTraversalTest.java | 12 ++--
3 files changed, 121 insertions(+), 4 deletions(-)
create mode 100644 src/main/java/com/thealgorithms/datastructures/trees/InorderTraversal.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/InorderTraversalTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/InorderTraversal.java b/src/main/java/com/thealgorithms/datastructures/trees/InorderTraversal.java
new file mode 100644
index 000000000000..6441375568ad
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/trees/InorderTraversal.java
@@ -0,0 +1,60 @@
+package com.thealgorithms.datastructures.trees;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
+
+/**
+ * Given tree is traversed in an 'inorder' way: LEFT -> ROOT -> RIGHT.
+ * Below are given the recursive and iterative implementations.
+ *
+ * Complexities:
+ * Recursive: O(n) - time, O(n) - space, where 'n' is the number of nodes in a tree.
+ *
+ * Iterative: O(n) - time, O(h) - space, where 'n' is the number of nodes in a tree
+ * and 'h' is the height of a binary tree.
+ * In the worst case 'h' can be O(n) if tree is completely unbalanced, for instance:
+ * 5
+ * \
+ * 6
+ * \
+ * 7
+ * \
+ * 8
+ *
+ * @author Albina Gimaletdinova on 21/02/2023
+ */
+public class InorderTraversal {
+ public static List recursiveInorder(BinaryTree.Node root) {
+ List result = new ArrayList<>();
+ recursiveInorder(root, result);
+ return result;
+ }
+
+ public static List iterativeInorder(BinaryTree.Node root) {
+ List result = new ArrayList<>();
+ if (root == null) return result;
+
+ Deque stack = new ArrayDeque<>();
+ while (!stack.isEmpty() || root != null) {
+ while (root != null) {
+ stack.push(root);
+ root = root.left;
+ }
+ root = stack.pop();
+ result.add(root.data);
+ root = root.right;
+ }
+ return result;
+ }
+
+ private static void recursiveInorder(BinaryTree.Node root, List result) {
+ if (root == null) {
+ return;
+ }
+ recursiveInorder(root.left, result);
+ result.add(root.data);
+ recursiveInorder(root.right, result);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/InorderTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/InorderTraversalTest.java
new file mode 100644
index 000000000000..6b882cae8e04
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/InorderTraversalTest.java
@@ -0,0 +1,53 @@
+package com.thealgorithms.datastructures.trees;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Albina Gimaletdinova on 21/02/2023
+ */
+public class InorderTraversalTest {
+ @Test
+ public void testNullRoot() {
+ assertEquals(Collections.emptyList(), InorderTraversal.recursiveInorder(null));
+ assertEquals(Collections.emptyList(), InorderTraversal.iterativeInorder(null));
+ }
+
+ /*
+ 1
+ / \
+ 2 3
+ /\ /\
+ 4 5 6 7
+ */
+ @Test
+ public void testRecursiveInorder() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
+ List expected = List.of(4, 2, 5, 1, 6, 3, 7);
+
+ assertEquals(expected, InorderTraversal.recursiveInorder(root));
+ assertEquals(expected, InorderTraversal.iterativeInorder(root));
+ }
+
+ /*
+ 5
+ \
+ 6
+ \
+ 7
+ \
+ 8
+ */
+ @Test
+ public void testRecursiveInorderNonBalanced() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{5, null, 6, null, 7, null, 8});
+ List expected = List.of(5, 6, 7, 8);
+
+ assertEquals(expected, InorderTraversal.recursiveInorder(root));
+ assertEquals(expected, InorderTraversal.iterativeInorder(root));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java
index eeac2131a78b..6f4106978a06 100644
--- a/src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java
@@ -27,8 +27,10 @@ public void testNullRoot() {
@Test
public void testRecursivePreOrder() {
final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
- assertEquals(List.of(1, 2, 4, 5, 3, 6, 7), PreOrderTraversal.recursivePreOrder(root));
- assertEquals(List.of(1, 2, 4, 5, 3, 6, 7), PreOrderTraversal.iterativePreOrder(root));
+ List expected = List.of(1, 2, 4, 5, 3, 6, 7);
+
+ assertEquals(expected, PreOrderTraversal.recursivePreOrder(root));
+ assertEquals(expected, PreOrderTraversal.iterativePreOrder(root));
}
/*
@@ -43,7 +45,9 @@ public void testRecursivePreOrder() {
@Test
public void testRecursivePreOrderNonBalanced() {
final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{5, null, 6, null, 7, null, 8});
- assertEquals(List.of(5, 6, 7, 8), PreOrderTraversal.recursivePreOrder(root));
- assertEquals(List.of(5, 6, 7, 8), PreOrderTraversal.iterativePreOrder(root));
+ List expected = List.of(5, 6, 7, 8);
+
+ assertEquals(expected, PreOrderTraversal.recursivePreOrder(root));
+ assertEquals(expected, PreOrderTraversal.iterativePreOrder(root));
}
}
From b98dc2c5b5e9ba46017d4f6fd3a2458087903ea9 Mon Sep 17 00:00:00 2001
From: Narek Karapetian
Date: Mon, 27 Feb 2023 01:15:48 +0400
Subject: [PATCH 0033/1088] Fix linear probing hash map (#3902)
---
.../hashmap/hashing/HashMapLinearProbing.java | 203 ------------------
.../hashmap/hashing/LinearProbingHashMap.java | 141 ++++++++++++
.../hashmap/hashing/MainLinearProbing.java | 69 ------
.../datastructures/hashmap/hashing/Map.java | 23 ++
.../hashing/LinearProbingHashMapTest.java | 8 +
.../hashmap/hashing/MapTest.java | 129 +++++++++++
6 files changed, 301 insertions(+), 272 deletions(-)
delete mode 100644 src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapLinearProbing.java
create mode 100644 src/main/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMap.java
delete mode 100644 src/main/java/com/thealgorithms/datastructures/hashmap/hashing/MainLinearProbing.java
create mode 100644 src/main/java/com/thealgorithms/datastructures/hashmap/hashing/Map.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMapTest.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapLinearProbing.java b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapLinearProbing.java
deleted file mode 100644
index c8ed333a5595..000000000000
--- a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapLinearProbing.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package com.thealgorithms.datastructures.hashmap.hashing;
-
-import java.util.*;
-
-/**
- * This class is an implementation of a hash table using linear probing It uses
- * a dynamic array to lengthen the size of the hash table when load factor > .7
- */
-public class HashMapLinearProbing {
-
- private int hsize; // size of the hash table
- private Integer[] buckets; // array representing the table
- private Integer AVAILABLE;
- private int size; // amount of elements in the hash table
-
- /**
- * Constructor initializes buckets array, hsize, and creates dummy object
- * for AVAILABLE
- *
- * @param hsize the desired size of the hash map
- */
- public HashMapLinearProbing(int hsize) {
- this.buckets = new Integer[hsize];
- this.hsize = hsize;
- this.AVAILABLE = Integer.MIN_VALUE;
- this.size = 0;
- }
-
- /**
- * The Hash Function takes a given key and finds an index based on its data
- *
- * @param key the desired key to be converted
- * @return int an index corresponding to the key
- */
- public int hashing(int key) {
- int hash = key % hsize;
- if (hash < 0) {
- hash += hsize;
- }
- return hash;
- }
-
- /**
- * inserts the key into the hash map by wrapping it as an Integer object
- *
- * @param key the desired key to be inserted in the hash map
- */
- public void insertHash(int key) {
- Integer wrappedInt = key;
- int hash = hashing(key);
-
- if (isFull()) {
- System.out.println("Hash table is full");
- return;
- }
-
- for (int i = 0; i < hsize; i++) {
- if (buckets[hash] == null || buckets[hash] == AVAILABLE) {
- buckets[hash] = wrappedInt;
- size++;
- return;
- }
-
- if (hash + 1 < hsize) {
- hash++;
- } else {
- hash = 0;
- }
- }
- }
-
- /**
- * deletes a key from the hash map and adds an available placeholder
- *
- * @param key the desired key to be deleted
- */
- public void deleteHash(int key) {
- Integer wrappedInt = key;
- int hash = hashing(key);
-
- if (isEmpty()) {
- System.out.println("Table is empty");
- return;
- }
-
- for (int i = 0; i < hsize; i++) {
- if (buckets[hash] != null && buckets[hash].equals(wrappedInt)) {
- buckets[hash] = AVAILABLE;
- size--;
- return;
- }
-
- if (hash + 1 < hsize) {
- hash++;
- } else {
- hash = 0;
- }
- }
- System.out.println("Key " + key + " not found");
- }
-
- /**
- * Displays the hash table line by line
- */
- public void displayHashtable() {
- for (int i = 0; i < hsize; i++) {
- if (buckets[i] == null || buckets[i] == AVAILABLE) {
- System.out.println("Bucket " + i + ": Empty");
- } else {
- System.out.println(
- "Bucket " + i + ": " + buckets[i].toString()
- );
- }
- }
- }
-
- /**
- * Finds the index of location based on an inputed key
- *
- * @param key the desired key to be found
- * @return int the index where the key is located
- */
- public int findHash(int key) {
- Integer wrappedInt = key;
- int hash = hashing(key);
-
- if (isEmpty()) {
- System.out.println("Table is empty");
- return -1;
- }
-
- for (int i = 0; i < hsize; i++) {
- try {
- if (buckets[hash].equals(wrappedInt)) {
- buckets[hash] = AVAILABLE;
- return hash;
- }
- } catch (Exception E) {}
-
- if (hash + 1 < hsize) {
- hash++;
- } else {
- hash = 0;
- }
- }
- System.out.println("Key " + key + " not found");
- return -1;
- }
-
- private void lengthenTable() {
- buckets = Arrays.copyOf(buckets, hsize * 2);
- hsize *= 2;
- System.out.println("Table size is now: " + hsize);
- }
-
- /**
- * Checks the load factor of the hash table if greater than .7,
- * automatically lengthens table to prevent further collisions
- */
- public void checkLoadFactor() {
- double factor = (double) size / hsize;
- if (factor > .7) {
- System.out.println(
- "Load factor is " + factor + ", lengthening table"
- );
- lengthenTable();
- } else {
- System.out.println("Load factor is " + factor);
- }
- }
-
- /**
- * isFull returns true if the hash map is full and false if not full
- *
- * @return boolean is Empty
- */
- public boolean isFull() {
- boolean response = true;
- for (int i = 0; i < hsize; i++) {
- if (buckets[i] == null || buckets[i] == AVAILABLE) {
- response = false;
- break;
- }
- }
- return response;
- }
-
- /**
- * isEmpty returns true if the hash map is empty and false if not empty
- *
- * @return boolean is Empty
- */
- public boolean isEmpty() {
- boolean response = true;
- for (int i = 0; i < hsize; i++) {
- if (buckets[i] != null) {
- response = false;
- break;
- }
- }
- return response;
- }
-}
diff --git a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMap.java b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMap.java
new file mode 100644
index 000000000000..c96da27c0331
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMap.java
@@ -0,0 +1,141 @@
+package com.thealgorithms.datastructures.hashmap.hashing;
+
+import java.util.ArrayList;
+
+/***
+ * This class is an implementation of a hash table using linear probing.
+ * @see Linear Probing Hash Table
+ *
+ * @param keys type.
+ * @param values type.
+ */
+public class LinearProbingHashMap, Value> extends Map {
+ private int hsize; // size of the hash table
+ private Key[] keys;
+ private Value[] values;
+ private int size; // amount of elements in the hash table
+
+ public LinearProbingHashMap() {
+ this(16);
+ }
+
+ @SuppressWarnings("unchecked")
+ public LinearProbingHashMap(int size) {
+ this.hsize = size;
+ keys = (Key[]) new Comparable[size];
+ values = (Value[]) new Object[size];
+ }
+
+ @Override
+ public boolean put(Key key, Value value) {
+ if (key == null) {
+ return false;
+ }
+
+ if (size > hsize / 2) {
+ resize(2 * hsize);
+ }
+
+ int keyIndex = hash(key, hsize);
+ for (; keys[keyIndex] != null; keyIndex = increment(keyIndex)) {
+ if (key.equals(keys[keyIndex])) {
+ values[keyIndex] = value;
+ return true;
+ }
+ }
+
+ keys[keyIndex] = key;
+ values[keyIndex] = value;
+ size++;
+ return true;
+ }
+
+ @Override
+ public Value get(Key key) {
+ if (key == null) {
+ return null;
+ }
+
+ for (int i = hash(key, hsize); keys[i] != null; i = increment(i)) {
+ if (key.equals(keys[i])) {
+ return values[i];
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean delete(Key key) {
+ if (key == null || !contains(key)) {
+ return false;
+ }
+
+ int i = hash(key, hsize);
+ while (!key.equals(keys[i])) {
+ i = increment(i);
+ }
+
+ keys[i] = null;
+ values[i] = null;
+
+ i = increment(i);
+ while (keys[i] != null) {
+ // delete keys[i] an vals[i] and reinsert
+ Key keyToRehash = keys[i];
+ Value valToRehash = values[i];
+ keys[i] = null;
+ values[i] = null;
+ size--;
+ put(keyToRehash, valToRehash);
+ i = increment(i);
+ }
+
+ size--;
+ if (size > 0 && size <= hsize / 8) {
+ resize(hsize / 2);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean contains(Key key) {
+ return get(key) != null;
+ }
+
+ @Override
+ int size() {
+ return size;
+ }
+
+ @Override
+ Iterable keys() {
+ ArrayList listOfKeys = new ArrayList<>(size);
+ for (int i = 0; i < hsize; i++) {
+ if (keys[i] != null) {
+ listOfKeys.add(keys[i]);
+ }
+ }
+
+ listOfKeys.sort(Comparable::compareTo);
+ return listOfKeys;
+ }
+
+ private int increment(int i) {
+ return (i + 1) % hsize;
+ }
+
+ private void resize(int newSize) {
+ LinearProbingHashMap tmp = new LinearProbingHashMap<>(newSize);
+ for (int i = 0; i < hsize; i++) {
+ if (keys[i] != null) {
+ tmp.put(keys[i], values[i]);
+ }
+ }
+
+ this.keys = tmp.keys;
+ this.values = tmp.values;
+ this.hsize = newSize;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/MainLinearProbing.java b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/MainLinearProbing.java
deleted file mode 100644
index bd75d171adf4..000000000000
--- a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/MainLinearProbing.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.thealgorithms.datastructures.hashmap.hashing;
-
-import java.util.Scanner;
-
-public class MainLinearProbing {
-
- public static void main(String[] args) {
- int choice, key;
-
- HashMapLinearProbing h = new HashMapLinearProbing(7);
- Scanner In = new Scanner(System.in);
-
- while (true) {
- System.out.println("Enter your Choice :");
- System.out.println("1. Add Key");
- System.out.println("2. Delete Key");
- System.out.println("3. Print Table");
- System.out.println("4. Exit");
- System.out.println("5. Search and print key index");
- System.out.println("6. Check load factor");
-
- choice = In.nextInt();
-
- switch (choice) {
- case 1:
- {
- System.out.println("Enter the Key: ");
- key = In.nextInt();
- h.insertHash(key);
- break;
- }
- case 2:
- {
- System.out.println("Enter the Key delete: ");
- key = In.nextInt();
- h.deleteHash(key);
- break;
- }
- case 3:
- {
- System.out.println("Print table");
- h.displayHashtable();
- break;
- }
- case 4:
- {
- In.close();
- return;
- }
- case 5:
- {
- System.out.println(
- "Enter the Key to find and print: "
- );
- key = In.nextInt();
- System.out.println(
- "Key: " + key + " is at index: " + h.findHash(key)
- );
- break;
- }
- case 6:
- {
- h.checkLoadFactor();
- break;
- }
- }
- }
- }
-}
diff --git a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/Map.java b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/Map.java
new file mode 100644
index 000000000000..cd27b0a795b2
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/Map.java
@@ -0,0 +1,23 @@
+package com.thealgorithms.datastructures.hashmap.hashing;
+
+public abstract class Map {
+
+ abstract boolean put(Key key, Value value);
+
+ abstract Value get(Key key);
+
+ abstract boolean delete(Key key);
+
+ abstract Iterable keys();
+
+ abstract int size();
+
+ public boolean contains(Key key) {
+ return get(key) != null;
+ }
+
+ protected int hash(Key key, int size) {
+ return (key.hashCode() & Integer.MAX_VALUE) % size;
+ }
+
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMapTest.java b/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMapTest.java
new file mode 100644
index 000000000000..d0a72a1509ee
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMapTest.java
@@ -0,0 +1,8 @@
+package com.thealgorithms.datastructures.hashmap.hashing;
+
+class LinearProbingHashMapTest extends MapTest {
+ @Override
+ , Value> Map getMap() {
+ return new LinearProbingHashMap<>();
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java b/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java
new file mode 100644
index 000000000000..5ccbcc304d94
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java
@@ -0,0 +1,129 @@
+package com.thealgorithms.datastructures.hashmap.hashing;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Random;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+abstract class MapTest {
+ abstract , Value> Map getMap();
+
+ @Test
+ void putTest() {
+ Map map = getMap();
+
+ assertFalse(map.put(null, "-25"));
+ assertFalse(map.put(null, null));
+ assertTrue(map.put(-25, "-25"));
+ assertTrue(map.put(33, "33"));
+ assertTrue(map.put(100, "100"));
+ assertTrue(map.put(100, "+100"));
+ assertTrue(map.put(100, null));
+ }
+
+ @Test
+ void getTest() {
+ Map map = getMap();
+ for (int i = -100; i < 100; i++) {
+ map.put(i, String.valueOf(i));
+ }
+
+ for (int i = -100; i < 100; i++) {
+ assertEquals(map.get(i), String.valueOf(i));
+ }
+
+ for (int i = 100; i < 200; i++) {
+ assertNull(map.get(i));
+ }
+
+ assertNull(map.get(null));
+ }
+
+ @Test
+ void deleteTest() {
+ Map map = getMap();
+ for (int i = -100; i < 100; i++) {
+ map.put(i, String.valueOf(i));
+ }
+
+ for (int i = 0; i < 100; i++) {
+ assertTrue(map.delete(i));
+ }
+
+ for (int i = 100; i < 200; i++) {
+ assertFalse(map.delete(i));
+ }
+
+ assertFalse(map.delete(null));
+ }
+
+ @Test
+ void containsTest() {
+ Map map = getMap();
+ for (int i = -100; i < 100; i++) {
+ map.put(i, String.valueOf(i));
+ }
+
+ for (int i = -50; i < 50; i++) {
+ assertTrue(map.contains(i));
+ }
+
+ for (int i = 100; i < 200; i++) {
+ assertFalse(map.contains(i));
+ }
+
+ assertFalse(map.contains(null));
+ }
+
+ @Test
+ void sizeTest() {
+ Map map = getMap();
+ assertEquals(map.size(), 0);
+
+ for (int i = -100; i < 100; i++) {
+ map.put(i, String.valueOf(i));
+ }
+
+ assertEquals(map.size(), 200);
+
+ for (int i = -50; i < 50; i++) {
+ map.delete(i);
+ }
+
+ assertEquals(map.size(), 100);
+ }
+
+ @Test
+ void keysTest() {
+ Map map = getMap();
+ Iterable keys = map.keys();
+ assertFalse(keys.iterator().hasNext());
+
+ for (int i = 100; i > -100; i--) {
+ map.put(i, String.valueOf(i));
+ }
+
+ keys = map.keys();
+ int i = -100;
+ for (Integer key : keys) {
+ assertEquals(key, ++i);
+ }
+ }
+
+ @Test
+ void hashTest() {
+ Map map = getMap();
+ int testSize = 100;
+ Random random = new Random();
+ for (int i = 0; i < 1000; i++) {
+ int randomInt = random.nextInt();
+ int hashIndex = map.hash(randomInt, testSize);
+ int negateHashIndex = map.hash(-randomInt, testSize);
+ assertTrue(hashIndex >= 0);
+ assertTrue(hashIndex < testSize);
+ assertTrue(negateHashIndex >= 0);
+ assertTrue(negateHashIndex < testSize);
+ }
+ }
+}
From 3499c1bee6659db08f40abebc4e72d9bdfeec8f4 Mon Sep 17 00:00:00 2001
From: Albina Gimaletdinova
Date: Mon, 27 Feb 2023 15:06:39 +0300
Subject: [PATCH 0034/1088] Add postorder binary tree traversal (#3899)
---
.../trees/PostOrderTraversal.java | 62 +++++++++++++++++++
.../trees/PostOrderTraversalTest.java | 55 ++++++++++++++++
2 files changed, 117 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/trees/PostOrderTraversal.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/PostOrderTraversalTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/trees/PostOrderTraversal.java b/src/main/java/com/thealgorithms/datastructures/trees/PostOrderTraversal.java
new file mode 100644
index 000000000000..f7afb60ac348
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/trees/PostOrderTraversal.java
@@ -0,0 +1,62 @@
+package com.thealgorithms.datastructures.trees;
+
+import java.util.*;
+
+/**
+ * Given tree is traversed in a 'post-order' way: LEFT -> RIGHT -> ROOT.
+ * Below are given the recursive and iterative implementations.
+ *
+ * Complexities:
+ * Recursive: O(n) - time, O(n) - space, where 'n' is the number of nodes in a tree.
+ *
+ * Iterative: O(n) - time, O(h) - space, where 'n' is the number of nodes in a tree
+ * and 'h' is the height of a binary tree.
+ * In the worst case 'h' can be O(n) if tree is completely unbalanced, for instance:
+ * 5
+ * \
+ * 6
+ * \
+ * 7
+ * \
+ * 8
+ *
+ * @author Albina Gimaletdinova on 21/02/2023
+ */
+public class PostOrderTraversal {
+ public static List recursivePostOrder(BinaryTree.Node root) {
+ List result = new ArrayList<>();
+ recursivePostOrder(root, result);
+ return result;
+ }
+
+ public static List iterativePostOrder(BinaryTree.Node root) {
+ LinkedList result = new LinkedList<>();
+ if (root == null) {
+ return result;
+ }
+
+ Deque stack = new ArrayDeque<>();
+ stack.push(root);
+ while (!stack.isEmpty()) {
+ BinaryTree.Node node = stack.pop();
+ result.addFirst(node.data);
+ if (node.left != null) {
+ stack.push(node.left);
+ }
+ if (node.right != null) {
+ stack.push(node.right);
+ }
+ }
+
+ return result;
+ }
+
+ private static void recursivePostOrder(BinaryTree.Node root, List result) {
+ if (root == null) {
+ return;
+ }
+ recursivePostOrder(root.left, result);
+ recursivePostOrder(root.right, result);
+ result.add(root.data);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/PostOrderTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/PostOrderTraversalTest.java
new file mode 100644
index 000000000000..2774dc099938
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/PostOrderTraversalTest.java
@@ -0,0 +1,55 @@
+package com.thealgorithms.datastructures.trees;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Given tree is traversed in a 'post-order' way: LEFT -> RIGHT -> ROOT.
+ *
+ * @author Albina Gimaletdinova on 21/02/2023
+ */
+public class PostOrderTraversalTest {
+ @Test
+ public void testNullRoot() {
+ assertEquals(Collections.emptyList(), PostOrderTraversal.recursivePostOrder(null));
+ assertEquals(Collections.emptyList(), PostOrderTraversal.iterativePostOrder(null));
+ }
+
+ /*
+ 1
+ / \
+ 2 3
+ /\ /\
+ 4 5 6 7
+ */
+ @Test
+ public void testPostOrder() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{1, 2, 3, 4, 5, 6, 7});
+ List expected = List.of(4, 5, 2, 6, 7, 3, 1);
+
+ assertEquals(expected, PostOrderTraversal.recursivePostOrder(root));
+ assertEquals(expected, PostOrderTraversal.iterativePostOrder(root));
+ }
+
+ /*
+ 5
+ \
+ 6
+ \
+ 7
+ \
+ 8
+ */
+ @Test
+ public void testPostOrderNonBalanced() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[]{5, null, 6, null, 7, null, 8});
+ List expected = List.of(8, 7, 6, 5);
+
+ assertEquals(expected, PostOrderTraversal.recursivePostOrder(root));
+ assertEquals(expected, PostOrderTraversal.iterativePostOrder(root));
+ }
+}
From f3613382aab6b15e50560a759c9b6e41038a6515 Mon Sep 17 00:00:00 2001
From: Siddhant Swarup Mallick <78552027+siddhant2002@users.noreply.github.com>
Date: Tue, 28 Feb 2023 16:16:17 +0530
Subject: [PATCH 0035/1088] Add All Paths from Source to Target (fixes #3359)
(#3873)
---
.../AllPathsFromSourceToTarget.java | 108 ++++++++++++++++++
.../AllPathsFromSourceToTargetTest.java | 56 +++++++++
2 files changed, 164 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/backtracking/AllPathsFromSourceToTarget.java
create mode 100644 src/test/java/com/thealgorithms/backtracking/AllPathsFromSourceToTargetTest.java
diff --git a/src/main/java/com/thealgorithms/backtracking/AllPathsFromSourceToTarget.java b/src/main/java/com/thealgorithms/backtracking/AllPathsFromSourceToTarget.java
new file mode 100644
index 000000000000..424c451edb55
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/AllPathsFromSourceToTarget.java
@@ -0,0 +1,108 @@
+/** Author : Siddhant Swarup Mallick
+ * Github : https://github.com/siddhant2002
+ */
+
+/** Program description - To find all possible paths from source to destination*/
+
+/**Wikipedia link -> https://en.wikipedia.org/wiki/Shortest_path_problem */
+package com.thealgorithms.backtracking;
+
+import java.util.*;
+
+public class AllPathsFromSourceToTarget {
+
+ // No. of vertices in graph
+ private int v;
+
+ // To store the paths from source to destination
+ static List> nm=new ArrayList<>();
+ // adjacency list
+ private ArrayList[] adjList;
+
+ // Constructor
+ public AllPathsFromSourceToTarget(int vertices)
+ {
+
+ // initialise vertex count
+ this.v = vertices;
+
+ // initialise adjacency list
+ initAdjList();
+ }
+
+ // utility method to initialise adjacency list
+ private void initAdjList()
+ {
+ adjList = new ArrayList[v];
+
+ for (int i = 0; i < v; i++) {
+ adjList[i] = new ArrayList<>();
+ }
+ }
+
+ // add edge from u to v
+ public void addEdge(int u, int v)
+ {
+ // Add v to u's list.
+ adjList[u].add(v);
+ }
+
+
+ public void storeAllPaths(int s, int d)
+ {
+ boolean[] isVisited = new boolean[v];
+ ArrayList pathList = new ArrayList<>();
+
+ // add source to path[]
+ pathList.add(s);
+ // Call recursive utility
+ storeAllPathsUtil(s, d, isVisited, pathList);
+ }
+
+ // A recursive function to print all paths from 'u' to 'd'.
+ // isVisited[] keeps track of vertices in current path.
+ // localPathList<> stores actual vertices in the current path
+ private void storeAllPathsUtil(Integer u, Integer d, boolean[] isVisited, List localPathList)
+ {
+
+ if (u.equals(d)) {
+ nm.add(new ArrayList<>(localPathList));
+ return;
+ }
+
+ // Mark the current node
+ isVisited[u] = true;
+
+ // Recursion for all the vertices adjacent to current vertex
+
+ for (Integer i : adjList[u]) {
+ if (!isVisited[i]) {
+ // store current node in path[]
+ localPathList.add(i);
+ storeAllPathsUtil(i, d, isVisited, localPathList);
+
+ // remove current node in path[]
+ localPathList.remove(i);
+ }
+ }
+
+ // Mark the current node
+ isVisited[u] = false;
+ }
+
+ // Driver program
+ public static List> allPathsFromSourceToTarget(int vertices, int a[][], int source, int destination)
+ {
+ // Create a sample graph
+ AllPathsFromSourceToTarget g = new AllPathsFromSourceToTarget(vertices);
+ for(int i=0 ; i> list2 = List.of(List.of(2, 0, 1, 3),List.of(2, 0, 3),List.of(2, 1, 3));
+ List> list1 = AllPathsFromSourceToTarget.allPathsFromSourceToTarget(vertices,a,source,destination);
+ list2=list1;
+ assertIterableEquals(list1, list2);
+ }
+
+ @Test
+ void testForSecondCase() {
+ int vertices = 5;
+ int a[][] = {{0,1},{0,2},{0,3},{2,0},{2,1},{1,3},{1,4},{3,4},{2,4}};
+ int source = 0;
+ int destination = 4;
+ List> list2 = List.of(List.of(0, 1, 3, 4),List.of(0, 1, 4),List.of(0, 2, 1, 3, 4),List.of(0, 2, 1, 4),List.of(0, 2, 4),List.of(0, 3, 4));
+ List> list1 = AllPathsFromSourceToTarget.allPathsFromSourceToTarget(vertices,a,source,destination);
+ list2=list1;
+ assertIterableEquals(list1, list2);
+ }
+
+ @Test
+ void testForThirdCase() {
+ int vertices = 6;
+ int a[][] = {{1,0},{2,3},{0,4},{1,5},{4,3},{0,2},{0,3},{1,2},{0,5},{3,4},{2,5},{2,4}};
+ int source = 1;
+ int destination = 5;
+ List> list2 = List.of(List.of(1, 0, 2, 5),List.of(1, 0, 5),List.of(1, 5),List.of(1, 2, 5));
+ List> list1 = AllPathsFromSourceToTarget.allPathsFromSourceToTarget(vertices,a,source,destination);
+ list2=list1;
+ assertIterableEquals(list1, list2);
+ }
+
+ @Test
+ void testForFourthcase() {
+ int vertices = 3;
+ int a[][] = {{0,1},{0,2},{1,2}};
+ int source = 0;
+ int destination = 2;
+ List> list2 = List.of(List.of(0, 1, 2),List.of(0, 2));
+ List> list1 = AllPathsFromSourceToTarget.allPathsFromSourceToTarget(vertices,a,source,destination);
+ list2=list1;
+ assertIterableEquals(list1, list2);
+ }
+}
\ No newline at end of file
From 87f9ebcb29bed03306cf300af242103615aeace1 Mon Sep 17 00:00:00 2001
From: Siddhant Swarup Mallick <78552027+siddhant2002@users.noreply.github.com>
Date: Wed, 1 Mar 2023 20:46:32 +0530
Subject: [PATCH 0036/1088] Add Frizzy Number (fixes #3379) (#3906)
---
.../com/thealgorithms/maths/FrizzyNumber.java | 33 +++++++++++++
.../thealgorithms/maths/FrizzyNumberTest.java | 48 +++++++++++++++++++
2 files changed, 81 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/maths/FrizzyNumber.java
create mode 100644 src/test/java/com/thealgorithms/maths/FrizzyNumberTest.java
diff --git a/src/main/java/com/thealgorithms/maths/FrizzyNumber.java b/src/main/java/com/thealgorithms/maths/FrizzyNumber.java
new file mode 100644
index 000000000000..48d4fb3b5a46
--- /dev/null
+++ b/src/main/java/com/thealgorithms/maths/FrizzyNumber.java
@@ -0,0 +1,33 @@
+/** Author : Siddhant Swarup Mallick
+ * Github : https://github.com/siddhant2002
+ */
+
+/** Program description - To find the FrizzyNumber*/
+
+
+package com.thealgorithms.maths;
+
+public class FrizzyNumber {
+
+ /**
+ * Returns the n-th number that is a sum of powers
+ * of the given base.
+ * Example: base = 3 and n = 4
+ * Ascending order of sums of powers of 3 =
+ * 3^0 = 1, 3^1 = 3, 3^1 + 3^0 = 4, 3^2 + 3^0 = 9
+ * Ans = 9
+ *
+ * @param base The base whose n-th sum of powers is required
+ * @param n Index from ascending order of sum of powers of base
+ * @return n-th sum of powers of base
+ */
+ public static double getNthFrizzy(int base, int n) {
+ double final1 = 0.0;
+ int i = 0;
+ do
+ {
+ final1 += Math.pow(base, i++) * (n % 2);
+ } while ((n /= 2) > 0);
+ return final1;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/FrizzyNumberTest.java b/src/test/java/com/thealgorithms/maths/FrizzyNumberTest.java
new file mode 100644
index 000000000000..1a8501eabe9e
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/FrizzyNumberTest.java
@@ -0,0 +1,48 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+public class FrizzyNumberTest {
+ @Test
+ public void testFrizziesForBase2() {
+ assertEquals(
+ 1,
+ FrizzyNumber.getNthFrizzy(2, 1));
+ assertEquals(
+ 3,
+ FrizzyNumber.getNthFrizzy(2, 3));
+ assertEquals(
+ 1000,
+ FrizzyNumber.getNthFrizzy(2, 1000));
+ }
+
+ @Test
+ public void testFrizziesForBase3() {
+ assertEquals(
+ 1,
+ FrizzyNumber.getNthFrizzy(3, 1));
+ assertEquals(
+ 3,
+ FrizzyNumber.getNthFrizzy(3, 2));
+ assertEquals(
+ 29430,
+ FrizzyNumber.getNthFrizzy(3, 1000));
+ }
+
+ @Test
+ public void testFrizziesForBase69() {
+ assertEquals(
+ 1,
+ FrizzyNumber.getNthFrizzy(69, 1));
+ assertEquals(
+ 69,
+ FrizzyNumber.getNthFrizzy(69, 2));
+ assertEquals(
+ 328510,
+ FrizzyNumber.getNthFrizzy(69, 9));
+ assertEquals(
+ 333340,
+ FrizzyNumber.getNthFrizzy(69, 15));
+ }
+}
From dd949e9b5dc92f306c5c5eb345ce28e257a75d82 Mon Sep 17 00:00:00 2001
From: a-kbd <63161225+a-kbd@users.noreply.github.com>
Date: Sun, 5 Mar 2023 20:03:08 +0100
Subject: [PATCH 0037/1088] Increase test coverage (fixes #3895 #3896) (#3897)
---
.../com/thealgorithms/maths/LongDivision.java | 3 +
.../datastructures/trees/BinaryTreeTest.java | 78 +++++++++++++++++++
.../thealgorithms/maths/LongDivisionTest.java | 40 ++++++++--
.../others/CRCAlgorithmTest.java | 29 +++++++
.../com/thealgorithms/strings/MyAtoiTest.java | 24 +++++-
5 files changed, 166 insertions(+), 8 deletions(-)
create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/BinaryTreeTest.java
create mode 100644 src/test/java/com/thealgorithms/others/CRCAlgorithmTest.java
diff --git a/src/main/java/com/thealgorithms/maths/LongDivision.java b/src/main/java/com/thealgorithms/maths/LongDivision.java
index 88a0a2617be5..2578fe2e8814 100644
--- a/src/main/java/com/thealgorithms/maths/LongDivision.java
+++ b/src/main/java/com/thealgorithms/maths/LongDivision.java
@@ -11,6 +11,9 @@ public static int divide(int dividend, int divisor) {
long new_dividend_1 = dividend;
long new_divisor_1 = divisor;
+ if(divisor == 0){
+ return 0;
+ }
if (dividend < 0) {
new_dividend_1 = new_dividend_1 * -1;
}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/BinaryTreeTest.java b/src/test/java/com/thealgorithms/datastructures/trees/BinaryTreeTest.java
new file mode 100644
index 000000000000..2ed3b534ee8f
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/BinaryTreeTest.java
@@ -0,0 +1,78 @@
+package com.thealgorithms.datastructures.trees;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class BinaryTreeTest {
+
+ //checks that adding populating the tree and searching for data
+ //retrieves the expected data
+@Test
+void test1(){
+ BinaryTree t = new BinaryTree();
+ t.put(3);
+ t.put(5);
+ t.put(7);
+ t.put(9);
+ t.put(12);
+
+
+ assertEquals(t.find(5).data, 5);
+ assertEquals(t.find(7).data, 7);
+}
+
+ //checks that removing data from the tree
+ //properly removes and makes the new root the expected new root
+@Test
+void test2(){
+ BinaryTree t = new BinaryTree();
+ t.put(3);
+ t.put(5);
+ t.put(7);
+ t.put(9);
+ t.put(12);
+ t.remove(3);
+ t.remove(5);
+ t.remove(7);
+
+
+ assertEquals(t.getRoot().data, 9);
+}
+
+//checks that removing an unexistend node returns false
+// as specified by the documentation of the function
+@Test
+void test3(){
+ BinaryTree t = new BinaryTree();
+ t.put(3);
+ t.put(5);
+ t.put(7);
+ t.put(9);
+ t.put(12);
+
+ assertEquals(t.remove(9), true);
+ assertEquals(t.remove(398745987), false);
+}
+
+//check if the bfs, inOrder, preOrder and postOrder functions
+//worg as expected, also increases the coverage measures in
+//JaCoCo
+@Test
+void test4(){
+ BinaryTree t = new BinaryTree();
+ t.put(3);
+ t.put(5);
+ t.put(7);
+ t.put(9);
+ t.put(12);
+
+ t.bfs(t.find(12));
+ t.inOrder(t.getRoot());
+ t.preOrder(t.getRoot());
+ t.postOrder(t.getRoot());
+
+ assertEquals(t.remove(9), true);
+ assertEquals(t.remove(398745987), false);
+}
+}
diff --git a/src/test/java/com/thealgorithms/maths/LongDivisionTest.java b/src/test/java/com/thealgorithms/maths/LongDivisionTest.java
index c35b606a5595..65ee328c054a 100644
--- a/src/test/java/com/thealgorithms/maths/LongDivisionTest.java
+++ b/src/test/java/com/thealgorithms/maths/LongDivisionTest.java
@@ -5,21 +5,51 @@
import static org.junit.jupiter.api.Assertions.*;
public class LongDivisionTest {
-
+
+ // Requirement: Dividend (positive) is greater than divisor (positive), returns correct integer after division
@Test
void testOne() {
assertEquals(3, LongDivision.divide(10,3));
}
-
- @Test
+
+ // Requirement: Dividend (positive) is greater than divisor (negative), returns correct integer after division
+ @Test
void testTwo() {
assertEquals(-2, LongDivision.divide(7,-3));
}
-
- @Test
+ // Requirement: Dividend (positive) is greater than divisor (negative), returns correct integer after division
+ // Basically the same as in the first test
+ @Test
void testThree() {
assertEquals(10, LongDivision.divide(105,10));
}
+
+ // Requirement: Dividend (negative), divisor (positive), returns correct integer after division
+ // Tests the case where the dividend is less than 0.
+ @Test
+ void testNegativeDividend() {
+ assertEquals(-1, LongDivision.divide(-5,3));
+ }
+ // Requirement: Dividend (positive), divisor (positive), returns correct integer after division
+ // Tests the case where the dividend is less than the divisor. The test should return 0 in this case.
+ @Test
+ void testDividendLessThanDivisor() {
+ assertEquals(0, LongDivision.divide(3,5));
+ }
+
+ // Requirement: Dividend (neither), divisor (positive), returns correct integer after division
+ // Tests the case where the dividend is 0. This should return a 0.
+ @Test
+ void testDividendIsZero() {
+ assertEquals(0, LongDivision.divide(0,5));
+ }
+
+ // Requirement: Dividend (positive), divisor (neither), returns correct integer after division
+ // Tests the case where the divisor is 0. This should return a 0.
+ @Test
+ void testDivisionByZero() {
+ assertEquals(0, LongDivision.divide(5,0));
+ }
}
diff --git a/src/test/java/com/thealgorithms/others/CRCAlgorithmTest.java b/src/test/java/com/thealgorithms/others/CRCAlgorithmTest.java
new file mode 100644
index 000000000000..906ab829c264
--- /dev/null
+++ b/src/test/java/com/thealgorithms/others/CRCAlgorithmTest.java
@@ -0,0 +1,29 @@
+
+package com.thealgorithms.others;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class CRCAlgorithmTest {
+
+ @Test
+ void test1(){
+ CRCAlgorithm c = new CRCAlgorithm("10010101010100101010010000001010010101010", 10, 0.0);
+
+ //A bit-error rate of 0.0 should not provide any wrong messages
+ c.changeMess();
+ c.divideMessageWithP(false);
+ assertEquals(c.getWrongMess(), 0);
+ }
+
+ @Test
+ void test2(){
+ CRCAlgorithm c = new CRCAlgorithm("10010101010100101010010000001010010101010", 10, 1.0);
+
+ //A bit error rate of 1.0 should not provide any correct messages
+ c.changeMess();
+ c.divideMessageWithP(false);
+ assertEquals(c.getCorrectMess(), 0);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/strings/MyAtoiTest.java b/src/test/java/com/thealgorithms/strings/MyAtoiTest.java
index ef092ab2f318..29dda8c06b80 100644
--- a/src/test/java/com/thealgorithms/strings/MyAtoiTest.java
+++ b/src/test/java/com/thealgorithms/strings/MyAtoiTest.java
@@ -11,15 +11,33 @@ void testOne() {
assertEquals(42, MyAtoi.myAtoi("42"));
}
- @Test
+ @Test
void testTwo() {
assertEquals(-42, MyAtoi.myAtoi(" -42"));
}
-
- @Test
+ @Test
void testThree() {
assertEquals(4193, MyAtoi.myAtoi("4193 with words"));
}
+ @Test
+ void testFour() {
+ assertEquals(0, MyAtoi.myAtoi("0"));
+ }
+
+ @Test
+ void testFive() {
+ assertEquals(5678, MyAtoi.myAtoi("5678"));
+ }
+
+ @Test
+ void testSix() {
+ assertEquals(42, MyAtoi.myAtoi("+42"));
+ }
+
+ @Test
+ void testSeven() {
+ assertEquals(0, MyAtoi.myAtoi(" +0 "));
+ }
}
From 3e9dd776e5cc91c84e8206779ace3874c8d7491f Mon Sep 17 00:00:00 2001
From: Kumaraswamy B G <71964026+XomaDev@users.noreply.github.com>
Date: Mon, 6 Mar 2023 00:38:42 +0530
Subject: [PATCH 0038/1088] Make LinkedQueue generic (#3909)
---
.../datastructures/queues/LinkedQueue.java | 101 ++++++++++++------
.../queues/LinkedQueueTest.java | 29 +++++
2 files changed, 95 insertions(+), 35 deletions(-)
create mode 100644 src/test/java/com/thealgorithms/datastructures/queues/LinkedQueueTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/queues/LinkedQueue.java b/src/main/java/com/thealgorithms/datastructures/queues/LinkedQueue.java
index 770582b78e18..79fddb0ef518 100644
--- a/src/main/java/com/thealgorithms/datastructures/queues/LinkedQueue.java
+++ b/src/main/java/com/thealgorithms/datastructures/queues/LinkedQueue.java
@@ -1,23 +1,25 @@
package com.thealgorithms.datastructures.queues;
+import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.StringJoiner;
-public class LinkedQueue {
+public class LinkedQueue implements Iterable {
- class Node {
+ static class Node {
- int data;
- Node next;
+ T data;
+ Node next;
public Node() {
- this(0);
+ this(null);
}
- public Node(int data) {
+ public Node(T data) {
this(data, null);
}
- public Node(int data, Node next) {
+ public Node(T data, Node next) {
this.data = data;
this.next = next;
}
@@ -26,12 +28,12 @@ public Node(int data, Node next) {
/**
* Front of Queue
*/
- private Node front;
+ private Node front;
/**
* Rear of Queue
*/
- private Node rear;
+ private Node rear;
/**
* Size of Queue
@@ -42,7 +44,7 @@ public Node(int data, Node next) {
* Init LinkedQueue
*/
public LinkedQueue() {
- front = rear = new Node();
+ front = rear = new Node<>();
}
/**
@@ -58,15 +60,14 @@ public boolean isEmpty() {
* Add element to rear of queue
*
* @param data insert value
- * @return true if add successfully
*/
- public boolean enqueue(int data) {
- Node newNode = new Node(data);
+ public void enqueue(T data) {
+ Node newNode = new Node<>(data);
+
rear.next = newNode;
rear = newNode;
/* make rear point at last node */
size++;
- return true;
}
/**
@@ -74,14 +75,13 @@ public boolean enqueue(int data) {
*
* @return element at the front of queue
*/
- public int dequeue() {
+ public T dequeue() {
if (isEmpty()) {
throw new NoSuchElementException("queue is empty");
}
- Node destroy = front.next;
- int retValue = destroy.data;
+ Node destroy = front.next;
+ T retValue = destroy.data;
front.next = front.next.next;
- destroy = null;
/* clear let GC do it's work */
size--;
@@ -97,7 +97,7 @@ public int dequeue() {
*
* @return element at the front
*/
- public int peekFront() {
+ public T peekFront() {
if (isEmpty()) {
throw new NoSuchElementException("queue is empty");
}
@@ -109,13 +109,52 @@ public int peekFront() {
*
* @return element at the front
*/
- public int peekRear() {
+ public T peekRear() {
if (isEmpty()) {
throw new NoSuchElementException("queue is empty");
}
return rear.data;
}
+ /**
+ * Peeks the element at the index and
+ * returns the value
+ * @param pos at which to peek
+ */
+
+ public T peek(int pos) {
+ if (pos > size)
+ throw new IndexOutOfBoundsException(
+ "Position %s out of range!".formatted(pos));
+ Node node = front;
+ while (pos-- > 0)
+ node = node.next;
+ return node.data;
+ }
+
+ /**
+ * Node iterator, allows to travel through
+ * the nodes using for() loop or forEach(Consumer)
+ */
+
+ @Override
+ public Iterator iterator() {
+ return new Iterator<>() {
+
+ Node node = front;
+
+ @Override
+ public boolean hasNext() {
+ return node.next != null;
+ }
+
+ @Override
+ public T next() {
+ return (node = node.next).data;
+ }
+ };
+ }
+
/**
* Return size of queue
*
@@ -129,30 +168,22 @@ public int size() {
* Clear all nodes in queue
*/
public void clear() {
- while (!isEmpty()) {
+ while (size > 0)
dequeue();
- }
}
@Override
public String toString() {
- if (isEmpty()) {
- return "[]";
- }
- StringBuilder builder = new StringBuilder();
- Node cur = front.next;
- builder.append("[");
- while (cur != null) {
- builder.append(cur.data).append(", ");
- cur = cur.next;
- }
- builder.replace(builder.length() - 2, builder.length(), "]");
- return builder.toString();
+ StringJoiner join = new StringJoiner(", "); // separator of ', '
+ Node travel = front;
+ while ((travel = travel.next) != null)
+ join.add(String.valueOf(travel.data));
+ return '[' + join.toString() + ']';
}
/* Driver Code */
public static void main(String[] args) {
- LinkedQueue queue = new LinkedQueue();
+ LinkedQueue queue = new LinkedQueue<>();
assert queue.isEmpty();
queue.enqueue(1);
diff --git a/src/test/java/com/thealgorithms/datastructures/queues/LinkedQueueTest.java b/src/test/java/com/thealgorithms/datastructures/queues/LinkedQueueTest.java
new file mode 100644
index 000000000000..e153890ee204
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/queues/LinkedQueueTest.java
@@ -0,0 +1,29 @@
+package com.thealgorithms.datastructures.queues;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+
+class LinkedQueueTest {
+ @Test
+ public void testQue() {
+ LinkedQueue queue = new LinkedQueue<>();
+ for (int i = 1; i < 5; i++)
+ queue.enqueue(i);
+
+ assertEquals(queue.peekRear(), 4);
+ assertEquals(queue.peek(2), 2);
+
+ assertEquals(queue.peek(4), 4);
+
+ final int[] element = { 1 };
+
+ // iterates over all the elements present
+ // as in the form of nodes
+ queue.forEach(integer -> {
+ if (element[0]++ != integer)
+ throw new AssertionError();
+ });
+ }
+}
\ No newline at end of file
From b6563cf37ae7db33e3f3c8ad513acd905353c147 Mon Sep 17 00:00:00 2001
From: Kumaraswamy B G <71964026+XomaDev@users.noreply.github.com>
Date: Tue, 7 Mar 2023 13:43:46 +0530
Subject: [PATCH 0039/1088] Add Buffered Reader (#3910)
---
.../com/thealgorithms/io/BufferedReader.java | 193 ++++++++++++++++++
.../thealgorithms/io/BufferedReaderTest.java | 133 ++++++++++++
2 files changed, 326 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/io/BufferedReader.java
create mode 100644 src/test/java/com/thealgorithms/io/BufferedReaderTest.java
diff --git a/src/main/java/com/thealgorithms/io/BufferedReader.java b/src/main/java/com/thealgorithms/io/BufferedReader.java
new file mode 100644
index 000000000000..1012ce79690f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/io/BufferedReader.java
@@ -0,0 +1,193 @@
+package com.thealgorithms.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Mimics the actions of the Original buffered reader
+ * implements other actions, such as peek(n) to lookahead,
+ * block() to read a chunk of size {BUFFER SIZE}
+ *
+ * Author: Kumaraswamy B.G (Xoma Dev)
+ */
+public class BufferedReader {
+
+ private static final int DEFAULT_BUFFER_SIZE = 5;
+
+ /**
+ * Maximum number of bytes the buffer can hold.
+ * Value is changed when encountered Eof to not
+ * cause overflow read of 0 bytes
+ */
+
+ private int bufferSize;
+ private final byte[] buffer;
+
+ /**
+ * posRead -> indicates the next byte to read
+ */
+ private int posRead = 0, bufferPos = 0;
+
+ private boolean foundEof = false;
+
+ private InputStream input;
+
+ public BufferedReader(byte[] input) throws IOException {
+ this(new ByteArrayInputStream(input));
+ }
+
+ public BufferedReader(InputStream input) throws IOException {
+ this(input, DEFAULT_BUFFER_SIZE);
+ }
+
+ public BufferedReader(InputStream input, int bufferSize) throws IOException {
+ this.input = input;
+ if (input.available() == -1)
+ throw new IOException("Empty or already closed stream provided");
+
+ this.bufferSize = bufferSize;
+ buffer = new byte[bufferSize];
+ }
+
+ /**
+ * Reads a single byte from the stream
+ */
+ public int read() throws IOException {
+ if (needsRefill()) {
+ if (foundEof)
+ return -1;
+ // the buffer is empty, or the buffer has
+ // been completely read and needs to be refilled
+ refill();
+ }
+ return buffer[posRead++] & 0xff; // read and un-sign it
+ }
+
+ /**
+ * Number of bytes not yet been read
+ */
+
+ public int available() throws IOException {
+ int available = input.available();
+ if (needsRefill())
+ // since the block is already empty,
+ // we have no responsibility yet
+ return available;
+ return bufferPos - posRead + available;
+ }
+
+ /**
+ * Returns the next character
+ */
+
+ public int peek() throws IOException {
+ return peek(1);
+ }
+
+ /**
+ * Peeks and returns a value located at next {n}
+ */
+
+ public int peek(int n) throws IOException {
+ int available = available();
+ if (n >= available)
+ throw new IOException("Out of range, available %d, but trying with %d"
+ .formatted(available, n));
+ pushRefreshData();
+
+ if (n >= bufferSize)
+ throw new IllegalAccessError("Cannot peek %s, maximum upto %s (Buffer Limit)"
+ .formatted(n, bufferSize));
+ return buffer[n];
+ }
+
+ /**
+ * Removes the already read bytes from the buffer
+ * in-order to make space for new bytes to be filled up.
+ *
+ * This may also do the job to read first time data (whole buffer is empty)
+ */
+
+ private void pushRefreshData() throws IOException {
+ for (int i = posRead, j = 0; i < bufferSize; i++, j++)
+ buffer[j] = buffer[i];
+
+ bufferPos -= posRead;
+ posRead = 0;
+
+ // fill out the spaces that we've
+ // emptied
+ justRefill();
+ }
+
+ /**
+ * Reads one complete block of size {bufferSize}
+ * if found eof, the total length of array will
+ * be that of what's available
+ *
+ * @return a completed block
+ */
+ public byte[] readBlock() throws IOException {
+ pushRefreshData();
+
+ byte[] cloned = new byte[bufferSize];
+ // arraycopy() function is better than clone()
+ if (bufferPos >= 0)
+ System.arraycopy(buffer,
+ 0,
+ cloned,
+ 0,
+ // important to note that, bufferSize does not stay constant
+ // once the class is defined. See justRefill() function
+ bufferSize);
+ // we assume that already a chunk
+ // has been read
+ refill();
+ return cloned;
+ }
+
+ private boolean needsRefill() {
+ return bufferPos == 0 || posRead == bufferSize;
+ }
+
+ private void refill() throws IOException {
+ posRead = 0;
+ bufferPos = 0;
+ justRefill();
+ }
+
+ private void justRefill() throws IOException {
+ assertStreamOpen();
+
+ // try to fill in the maximum we can until
+ // we reach EOF
+ while (bufferPos < bufferSize) {
+ int read = input.read();
+ if (read == -1) {
+ // reached end-of-file, no more data left
+ // to be read
+ foundEof = true;
+ // rewrite the BUFFER_SIZE, to know that we've reached
+ // EOF when requested refill
+ bufferSize = bufferPos;
+ }
+ buffer[bufferPos++] = (byte) read;
+ }
+ }
+
+ private void assertStreamOpen() {
+ if (input == null)
+ throw new IllegalStateException("Input Stream already closed!");
+ }
+
+ public void close() throws IOException {
+ if (input != null) {
+ try {
+ input.close();
+ } finally {
+ input = null;
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/io/BufferedReaderTest.java b/src/test/java/com/thealgorithms/io/BufferedReaderTest.java
new file mode 100644
index 000000000000..a183881743f8
--- /dev/null
+++ b/src/test/java/com/thealgorithms/io/BufferedReaderTest.java
@@ -0,0 +1,133 @@
+package com.thealgorithms.io;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class BufferedReaderTest {
+ @Test
+ public void testPeeks() throws IOException {
+ String text = "Hello!\nWorld!";
+ int len = text.length();
+ byte[] bytes = text.getBytes();
+
+ ByteArrayInputStream input = new ByteArrayInputStream(bytes);
+ BufferedReader reader = new BufferedReader(input);
+
+ // read the first letter
+ assertEquals(reader.read(), 'H');
+ len--;
+ assertEquals(reader.available(), len);
+
+ // 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');
+ }
+
+ @Test
+ public void testMixes() throws IOException {
+ String text = "Hello!\nWorld!";
+ int len = text.length();
+ byte[] bytes = text.getBytes();
+
+ ByteArrayInputStream input = new ByteArrayInputStream(bytes);
+ BufferedReader reader = new BufferedReader(input);
+
+ // read the first letter
+ assertEquals(reader.read(), 'H'); // first letter
+ len--;
+
+ assertEquals(reader.peek(1), 'l'); // third later (second letter after 'H')
+ assertEquals(reader.read(), 'e'); // second letter
+ len--;
+ assertEquals(reader.available(), len);
+
+ // position: H[e]llo!\nWorld!
+ assertEquals(reader.peek(2), 'o'); // second l
+ assertEquals(reader.peek(3), '!');
+ assertEquals(reader.peek(4), '\n');
+
+ assertEquals(reader.read(), 'l'); // third letter
+ assertEquals(reader.peek(1), 'o'); // fourth letter
+
+ for (int i = 0; i < 6; i++)
+ reader.read();
+ try {
+ System.out.println((char) reader.peek(4));
+ } catch (Exception ignored) {
+ System.out.println("[cached intentional error]");
+ // intentional, for testing purpose
+ }
+ }
+
+ @Test
+ public void testBlockPractical() throws IOException {
+ String text = "!Hello\nWorld!";
+ byte[] bytes = text.getBytes();
+ int len = bytes.length;
+
+ ByteArrayInputStream input = new ByteArrayInputStream(bytes);
+ BufferedReader reader = new BufferedReader(input);
+
+
+ assertEquals(reader.peek(), 'H');
+ 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");
+ 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');
+
+ // the rest of the blocks
+ assertEquals(new String(reader.readBlock()), "rld!");
+ } else {
+ // should not reach
+ throw new IOException("Something not right");
+ }
+ }
+
+ @Test
+ public void randomTest() throws IOException {
+ Random random = new Random();
+
+ int len = random.nextInt(9999);
+ int bound = 256;
+
+ ByteArrayOutputStream stream = new ByteArrayOutputStream(len);
+ while (len-- > 0)
+ stream.write(random.nextInt(bound));
+
+ byte[] bytes = stream.toByteArray();
+ ByteArrayInputStream comparer = new ByteArrayInputStream(bytes);
+
+ int blockSize = random.nextInt(7) + 5;
+ BufferedReader reader = new BufferedReader(
+ new ByteArrayInputStream(bytes), blockSize);
+
+ for (int i = 0; i < 50; i++) {
+ if ((i & 1) == 0) {
+ assertEquals(comparer.read(), reader.read());
+ continue;
+ }
+ byte[] block = new byte[blockSize];
+ comparer.read(block);
+ byte[] read = reader.readBlock();
+
+ assertArrayEquals(block, read);
+ }
+ }
+}
\ No newline at end of file
From a7e76c57a075a677dd024be6715bd15de3785074 Mon Sep 17 00:00:00 2001
From: Enrique Clerici <115318468+TheClerici@users.noreply.github.com>
Date: Fri, 10 Mar 2023 15:29:49 -0600
Subject: [PATCH 0040/1088] feat: Backtracking algorithms (All combinations)
#3912 (#3917)
* ArrayCombination function which uses Combination.java by creating an array of 1 to n
* modified tests
---
.../backtracking/ArrayCombination.java | 29 +++++++++++
.../backtracking/ArrayCombinationTest.java | 50 +++++++++++++++++++
2 files changed, 79 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/backtracking/ArrayCombination.java
create mode 100644 src/test/java/com/thealgorithms/backtracking/ArrayCombinationTest.java
diff --git a/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java b/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java
new file mode 100644
index 000000000000..4238846786e4
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java
@@ -0,0 +1,29 @@
+package com.thealgorithms.backtracking;
+
+import java.util.*;
+
+/**
+ * Finds all permutations of 1...n of length k
+ * @author TheClerici (https://github.com/TheClerici)
+ */
+public class ArrayCombination {
+ private static int length;
+
+ /**
+ * Find all combinations of 1..n by creating an array and using backtracking in Combination.java
+ * @param n max value of the array.
+ * @param k length of combination
+ * @return a list of all combinations of length k. If k == 0, return null.
+ */
+ public static List> combination(int n, int k) {
+ if (n <= 0) {
+ return null;
+ }
+ length = k;
+ Integer[] arr = new Integer[n];
+ for (int i = 1; i <= n; i++) {
+ arr[i-1] = i;
+ }
+ return Combination.combination(arr, length);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/thealgorithms/backtracking/ArrayCombinationTest.java b/src/test/java/com/thealgorithms/backtracking/ArrayCombinationTest.java
new file mode 100644
index 000000000000..02527257ccc6
--- /dev/null
+++ b/src/test/java/com/thealgorithms/backtracking/ArrayCombinationTest.java
@@ -0,0 +1,50 @@
+package com.thealgorithms.backtracking;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.List;
+import java.util.TreeSet;
+import org.junit.jupiter.api.Test;
+
+public class ArrayCombinationTest {
+
+ @Test
+ void testNBeingZeroOrLess() {
+ List> zeroResult = ArrayCombination.combination(0, 1);
+ List> negativeResult = ArrayCombination.combination(-1, 1);
+ assertNull(zeroResult);
+ assertNull(negativeResult);
+ }
+
+ @Test
+ void testNoLengthElement() {
+ List> result = ArrayCombination.combination(2, 0);
+ assertNull(result);
+ }
+
+ @Test
+ void testLengthOne() {
+ List> result = ArrayCombination.combination(2, 1);
+ assert result != null;
+ assertEquals(1, result.get(0).iterator().next());
+ assertEquals(2, result.get(1).iterator().next());
+ }
+
+ @Test
+ void testLengthTwo() {
+ List> result = ArrayCombination.combination(2, 2);
+ assert result != null;
+ Integer[] arr = result.get(0).toArray(new Integer[2]);
+ assertEquals(1, arr[0]);
+ assertEquals(2, arr[1]);
+ }
+
+ @Test
+ void testLengthFive() {
+ List> result = ArrayCombination.combination(10, 5);
+ assert result != null;
+ Integer[] arr = result.get(0).toArray(new Integer[5]);
+ assertEquals(1, arr[0]);
+ assertEquals(5, arr[4]);
+ }
+}
From 2418604f7aa448edfdac18a258841ae3afcb462c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tr=E1=BA=A7n=20Quang=20D=E1=BB=B1?=
Date: Sun, 12 Mar 2023 18:49:17 +0700
Subject: [PATCH 0041/1088] Add tests for SinglyLinkedList (#3913)
---
.../lists/SinglyLinkedList.java | 18 ++++
.../lists/SinglyLinkedListTest.java | 102 ++++++++++++++++++
2 files changed, 120 insertions(+)
create mode 100644 src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java b/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java
index acb17923c1ea..03ce735f2f5e 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java
+++ b/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java
@@ -54,6 +54,24 @@ public boolean detectLoop() {
return false;
}
+ /**
+ * Return the node in the middle of the list
+ * If the length of the list is even then return item number length/2
+ * @return middle node of the list
+ */
+ public Node middle() {
+ if (head == null) {
+ return null;
+ }
+ Node firstCounter = head;
+ Node secondCounter = firstCounter.next;
+ while (secondCounter != null && secondCounter.next != null) {
+ firstCounter = firstCounter.next;
+ secondCounter = secondCounter.next.next;
+ }
+ return firstCounter;
+ }
+
/**
* Swaps nodes of two given values a and b.
*
diff --git a/src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java b/src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java
new file mode 100644
index 000000000000..b02fb433ad4a
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java
@@ -0,0 +1,102 @@
+package com.thealgorithms.datastructures.lists;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class SinglyLinkedListTest {
+
+ /**
+ * Initialize a list with natural order values with pre-defined length
+ * @param length
+ * @return linked list with pre-defined number of nodes
+ */
+ private SinglyLinkedList createSampleList(int length) {
+ List nodeList = new ArrayList<>();
+ for (int i = 1; i <= length; i++) {
+ Node node = new Node(i);
+ nodeList.add(node);
+ }
+
+ for (int i = 0; i < length - 1; i++) {
+ nodeList.get(i).next = nodeList.get(i+1);
+ }
+
+ return new SinglyLinkedList(nodeList.get(0), length);
+ }
+
+ @Test
+ void detectLoop() {
+ //List has cycle
+ Node firstNode = new Node(1);
+ Node secondNode = new Node(2);
+ Node thirdNode = new Node(3);
+ Node fourthNode = new Node(4);
+
+ firstNode.next = secondNode;
+ secondNode.next = thirdNode;
+ thirdNode.next = fourthNode;
+ fourthNode.next = firstNode;
+
+ SinglyLinkedList listHasLoop = new SinglyLinkedList(firstNode, 4);
+ assertTrue(listHasLoop.detectLoop());
+
+ SinglyLinkedList listHasNoLoop = createSampleList(5);
+ assertFalse(listHasNoLoop.detectLoop());
+ }
+
+ @Test
+ void middle() {
+ int oddNumberOfNode = 7;
+ SinglyLinkedList list = createSampleList(oddNumberOfNode);
+ assertEquals(oddNumberOfNode/2 + 1, list.middle().value);
+ int evenNumberOfNode = 8;
+ list = createSampleList(evenNumberOfNode);
+ assertEquals(evenNumberOfNode/2, list.middle().value);
+
+ //return null if empty
+ list = new SinglyLinkedList();
+ assertNull(list.middle());
+
+ //return head if there is only one node
+ list = createSampleList(1);
+ assertEquals(list.getHead(), list.middle());
+ }
+
+ @Test
+ void swap() {
+ SinglyLinkedList list = createSampleList(5);
+ assertEquals(1, list.getHead().value);
+ assertEquals(5, list.getNth(4));
+ list.swapNodes(1,5);
+ assertEquals(5, list.getHead().value);
+ assertEquals(1, list.getNth(4));
+ }
+
+ @Test
+ void clear() {
+ SinglyLinkedList list = createSampleList(5);
+ assertEquals(5, list.size());
+ list.clear();
+ assertEquals(0, list.size());
+ assertTrue(list.isEmpty());
+ }
+
+ @Test
+ void search() {
+ SinglyLinkedList list = createSampleList(10);
+ assertTrue(list.search(5));
+ assertFalse(list.search(20));
+ }
+
+ @Test
+ void deleteNth() {
+ SinglyLinkedList list = createSampleList(10);
+ assertTrue(list.search(7));
+ list.deleteNth(6); //Index 6 has value 7
+ assertFalse(list.search(7));
+ }
+}
\ No newline at end of file
From 3a56c963b3f1ad009db530388babf2497084f093 Mon Sep 17 00:00:00 2001
From: Christian Clauss
Date: Sat, 18 Mar 2023 09:03:32 +0100
Subject: [PATCH 0042/1088] Change Python version for directory workflow from
3.10 to 3.x to use newer and faster language versions (#3921)
---
.github/workflows/update_directory.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/update_directory.yml b/.github/workflows/update_directory.yml
index 4be3c2841871..7eec515580a2 100644
--- a/.github/workflows/update_directory.yml
+++ b/.github/workflows/update_directory.yml
@@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-python@v4
with:
- python-version: '3.10'
+ python-version: '3.x'
- name: Update Directory
shell: python
run: |
From 0b6fa5c3b8a5d1364e287888c280306d98120bdd Mon Sep 17 00:00:00 2001
From: Andrii Siriak