From 61ff1233e8dc7dbbd29cd2a9392df50e88f21166 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Tue, 15 Oct 2024 12:26:05 +0530 Subject: [PATCH 1/3] feat: Add `MedianFinder` new algorithm with Junit tests --- .../datastructures/heaps/MedianFinder.java | 59 +++++++++++++++++++ .../heaps/MedianFinderTest.java | 16 +++++ 2 files changed, 75 insertions(+) create mode 100644 src/main/java/com/thealgorithms/datastructures/heaps/MedianFinder.java create mode 100644 src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java diff --git a/src/main/java/com/thealgorithms/datastructures/heaps/MedianFinder.java b/src/main/java/com/thealgorithms/datastructures/heaps/MedianFinder.java new file mode 100644 index 000000000000..4e74aaec4a10 --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/heaps/MedianFinder.java @@ -0,0 +1,59 @@ +package com.thealgorithms.datastructures.heaps; + +import java.util.PriorityQueue; + +/** + * This class maintains the median of a dynamically changing data stream using + * two heaps: a max-heap and a min-heap. The max-heap stores the smaller half + * of the numbers, and the min-heap stores the larger half. + * This data structure ensures that retrieving the median is efficient. + * + * Time Complexity: + * - Adding a number: O(log n) due to heap insertion. + * - Finding the median: O(1). + * + * Space Complexity: O(n), where n is the total number of elements added. + * + * @author Hardvan + */ +public final class MedianFinder { + MedianFinder() { + } + + private PriorityQueue minHeap = new PriorityQueue<>(); + private PriorityQueue maxHeap = new PriorityQueue<>((a, b) -> b - a); + + /** + * Adds a new number to the data stream. The number is placed in the appropriate + * heap to maintain the balance between the two heaps. + * + * @param num the number to be added to the data stream + */ + public void addNum(int num) { + if (maxHeap.isEmpty() || num <= maxHeap.peek()) { + maxHeap.offer(num); + } else { + minHeap.offer(num); + } + + if (maxHeap.size() > minHeap.size() + 1) { + minHeap.offer(maxHeap.poll()); + } else if (minHeap.size() > maxHeap.size()) { + maxHeap.offer(minHeap.poll()); + } + } + + /** + * Finds the median of the numbers added so far. If the total number of elements + * is even, the median is the average of the two middle elements. If odd, the + * median is the middle element from the max-heap. + * + * @return the median of the numbers in the data stream + */ + public double findMedian() { + if (maxHeap.size() == minHeap.size()) { + return (maxHeap.peek() + minHeap.peek()) / 2.0; + } + return maxHeap.peek(); + } +} diff --git a/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java b/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java new file mode 100644 index 000000000000..77cf83e00bec --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java @@ -0,0 +1,16 @@ +package com.thealgorithms.datastructures.heaps; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +public class MedianFinderTest { + @Test + public void testMedianMaintenance() { + MedianFinder mf = new MedianFinder(); + mf.addNum(1); + mf.addNum(2); + assertEquals(1.5, mf.findMedian()); + mf.addNum(3); + assertEquals(2.0, mf.findMedian()); + } +} From 5c9fba2fbe97d55013b3f88f1d78b55891ddc2f4 Mon Sep 17 00:00:00 2001 From: Hardvan Date: Tue, 15 Oct 2024 06:56:23 +0000 Subject: [PATCH 2/3] Update directory --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 6073904a745e..8ab1a7edb4d8 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -169,6 +169,7 @@ * [HeapElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/HeapElement.java) * [LeftistHeap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java) * [MaxHeap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MaxHeap.java) + * [MedianFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MedianFinder.java) * [MinHeap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MinHeap.java) * [MinPriorityQueue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MinPriorityQueue.java) * lists @@ -802,6 +803,7 @@ * heaps * [FibonacciHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/FibonacciHeapTest.java) * [LeftistHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java) + * [MedianFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java) * lists * [CircleLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java) * [CreateAndDetectLoopTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CreateAndDetectLoopTest.java) From 4a06f8fc934143c545a6dc0a3876f8bd8f20c1e2 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Tue, 15 Oct 2024 12:26:32 +0530 Subject: [PATCH 3/3] Fix --- .../com/thealgorithms/datastructures/heaps/MedianFinderTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java b/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java index 77cf83e00bec..fcacb21fcfc3 100644 --- a/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java +++ b/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java @@ -1,6 +1,7 @@ package com.thealgorithms.datastructures.heaps; import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; public class MedianFinderTest {