diff --git a/src/main/java/com/thealgorithms/Heap/DesignTwitter.java b/src/main/java/com/thealgorithms/Heap/DesignTwitter.java new file mode 100644 index 000000000000..a17c3961cc5e --- /dev/null +++ b/src/main/java/com/thealgorithms/Heap/DesignTwitter.java @@ -0,0 +1,76 @@ +import java.util.*; + +class Twitter { + private static int timeStamp = 0; + private static class Tweet { + int id; + int time; + Tweet next; + + public Tweet(int id, int time) { + this.id = id; + this.time = time; + } + } + + + private Map> followMap; + + private Map tweetMap; + + public Twitter() { + followMap = new HashMap<>(); + tweetMap = new HashMap<>(); + } + + /** User posts a new tweet */ + public void postTweet(int userId, int tweetId) { + Tweet newTweet = new Tweet(tweetId, timeStamp++); + if (tweetMap.containsKey(userId)) { + newTweet.next = tweetMap.get(userId); + } + tweetMap.put(userId, newTweet); + } + + /** Retrieve the 10 most recent tweet ids in the user's news feed */ + public List getNewsFeed(int userId) { + List result = new ArrayList<>(); + // Min-heap to get most recent tweets first + PriorityQueue pq = new PriorityQueue<>((a, b) -> b.time - a.time); + + // Add own tweets + if (tweetMap.containsKey(userId)) { + pq.offer(tweetMap.get(userId)); + } + + // Add followees' tweets + if (followMap.containsKey(userId)) { + for (int followee : followMap.get(userId)) { + if (tweetMap.containsKey(followee)) { + pq.offer(tweetMap.get(followee)); + } + } + } + + // Retrieve top 10 tweets + while (!pq.isEmpty() && result.size() < 10) { + Tweet t = pq.poll(); + result.add(t.id); + if (t.next != null) pq.offer(t.next); + } + return result; + } + + + public void follow(int followerId, int followeeId) { + if (followerId == followeeId) return; // can’t follow self + followMap.putIfAbsent(followerId, new HashSet<>()); + followMap.get(followerId).add(followeeId); + } + + /** Follower unfollows a followee */ + public void unfollow(int followerId, int followeeId) { + if (!followMap.containsKey(followerId)) return; + followMap.get(followerId).remove(followeeId); + } +} diff --git a/src/main/java/com/thealgorithms/Heap/FindMedianfromDataStream.java b/src/main/java/com/thealgorithms/Heap/FindMedianfromDataStream.java new file mode 100644 index 000000000000..08bfe5f53df0 --- /dev/null +++ b/src/main/java/com/thealgorithms/Heap/FindMedianfromDataStream.java @@ -0,0 +1,57 @@ +import java.util.*; + +public class MedianFinder { + private PriorityQueue maxHeap; // left half (small) + private PriorityQueue minHeap; // right half (larger) + + public MedianFinder() { + // Max-heap stores the smaller half + maxHeap = new PriorityQueue<>(Collections.reverseOrder()); + // Min-heap stores the larger half + minHeap = new PriorityQueue<>(); + } + + + public void addNum(int num) { + // Step 1: Add to maxHeap + maxHeap.offer(num); + + // Step 2: Balance heaps (ensure all in maxHeap <= all in minHeap) + minHeap.offer(maxHeap.poll()); + + // Step 3: Maintain size property (maxHeap can be larger by 1) + if (maxHeap.size() < minHeap.size()) { + maxHeap.offer(minHeap.poll()); + } + } + + public double findMedian() { + if (maxHeap.size() == minHeap.size()) { + // Even number of elements → average of two middles + return (maxHeap.peek() + minHeap.peek()) / 2.0; + } else { + // Odd → top of maxHeap + return maxHeap.peek(); + } + } + + + public static void main(String[] args) { + MedianFinder mf = new MedianFinder(); + + mf.addNum(1); + System.out.println("After adding 1, Median = " + mf.findMedian()); + + mf.addNum(2); + System.out.println("After adding 2, Median = " + mf.findMedian()); + + mf.addNum(3); + System.out.println("After adding 3, Median = " + mf.findMedian()); + + mf.addNum(4); + System.out.println("After adding 4, Median = " + mf.findMedian()); + + mf.addNum(5); + System.out.println("After adding 5, Median = " + mf.findMedian()); + } +} diff --git a/src/main/java/com/thealgorithms/Heap/HandOfStraights.java b/src/main/java/com/thealgorithms/Heap/HandOfStraights.java new file mode 100644 index 000000000000..1f3dd2c02908 --- /dev/null +++ b/src/main/java/com/thealgorithms/Heap/HandOfStraights.java @@ -0,0 +1,42 @@ +import java.util.*; + +public class HandOfStraights { + + public static boolean isNStraightHand(int[] hand, int groupSize) { + // Base check + if (hand.length % groupSize != 0) return false; + + // Step 1: Count frequency of each card + TreeMap cardCount = new TreeMap<>(); + for (int card : hand) { + cardCount.put(card, cardCount.getOrDefault(card, 0) + 1); + } + + // Step 2: Iterate over cards in sorted order + for (int card : cardCount.keySet()) { + int freq = cardCount.get(card); + if (freq > 0) { // If we still have cards to group + + for (int next = card; next < card + groupSize; next++) { + if (cardCount.getOrDefault(next, 0) < freq) { + return false; + } + cardCount.put(next, cardCount.get(next) - freq); + } + } + } + + return true; + } + + + public static void main(String[] args) { + int[] hand1 = {1,2,3,6,2,3,4,7,8}; + int groupSize1 = 3; + System.out.println("Output 1: " + isNStraightHand(hand1, groupSize1)); // true + + int[] hand2 = {1,2,3,4,5}; + int groupSize2 = 4; + System.out.println("Output 2: " + isNStraightHand(hand2, groupSize2)); // false + } +} diff --git a/src/main/java/com/thealgorithms/Heap/IPO.java b/src/main/java/com/thealgorithms/Heap/IPO.java new file mode 100644 index 000000000000..b380be4291e9 --- /dev/null +++ b/src/main/java/com/thealgorithms/Heap/IPO.java @@ -0,0 +1,46 @@ +import java.util.*; + +public class IPO { + public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) { + int n = profits.length; + int[][] projects = new int[n][2]; + + // Combine capital and profit for each project + for (int i = 0; i < n; i++) { + projects[i][0] = capital[i]; + projects[i][1] = profits[i]; + } + + // Sort projects by required capital (ascending) + Arrays.sort(projects, Comparator.comparingInt(a -> a[0])); + + + PriorityQueue maxHeap = new PriorityQueue<>((a, b) -> b - a); + + int i = 0; + for (int t = 0; t < k; t++) { + // Add all affordable projects to the heap + while (i < n && projects[i][0] <= w) { + maxHeap.offer(projects[i][1]); + i++; + } + + // If no project is affordable, break early + if (maxHeap.isEmpty()) break; + + + w += maxHeap.poll(); // Pick the most profitable project + } + + return w; + } + + public static void main(String[] args) { + IPO obj = new IPO(); + int k = 2, w = 0; + int[] profits = {1, 2, 3}; + int[] capital = {0, 1, 1}; + + System.out.println(obj.findMaximizedCapital(k, w, profits, capital)); // Output: 4 + } +} diff --git a/src/main/java/com/thealgorithms/Heap/MergeKSortedList.java b/src/main/java/com/thealgorithms/Heap/MergeKSortedList.java new file mode 100644 index 000000000000..5aec40e0b17a --- /dev/null +++ b/src/main/java/com/thealgorithms/Heap/MergeKSortedList.java @@ -0,0 +1,54 @@ +import java.util.*; + +class MergeMSortedArrays { + static class Element { + int value; + int arrayIndex; + int elementIndex; + + Element(int value, int arrayIndex, int elementIndex) { + this.value = value; + this.arrayIndex = arrayIndex; + this.elementIndex = elementIndex; + } + } + + public static List mergeSortedArrays(int[][] arrays) { + PriorityQueue minHeap = new PriorityQueue<>(Comparator.comparingInt(e -> e.value)); + List result = new ArrayList<>(); + + // Step 1: Push the first element of each array + for (int i = 0; i < arrays.length; i++) { + if (arrays[i].length > 0) { + minHeap.offer(new Element(arrays[i][0], i, 0)); + } + } + + // Step 2: Extract the smallest element and push the next from same array + while (!minHeap.isEmpty()) { + Element current = minHeap.poll(); + result.add(current.value); + + int nextIndex = current.elementIndex + 1; + if (nextIndex < arrays[current.arrayIndex].length) { + minHeap.offer(new Element( + arrays[current.arrayIndex][nextIndex], + current.arrayIndex, + nextIndex + )); + } + } + + return result; + } + + public static void main(String[] args) { + int[][] arrays = { + {1, 4, 7}, + {2, 5, 8}, + {3, 6, 9} + }; + + System.out.println("Merged Sorted Array: " + mergeSortedArrays(arrays)); + } +} diff --git a/src/main/java/com/thealgorithms/Heap/SlidingWindowMax.java b/src/main/java/com/thealgorithms/Heap/SlidingWindowMax.java new file mode 100644 index 000000000000..fb72b473134d --- /dev/null +++ b/src/main/java/com/thealgorithms/Heap/SlidingWindowMax.java @@ -0,0 +1,32 @@ +import java.util.*; + +public class SlidingWindowMaximum { + public static int[] maxSlidingWindow(int[] nums, int k) { + int n = nums.length; + int[] result = new int[n - k + 1]; + PriorityQueue maxHeap = new PriorityQueue<>((a, b) -> b[0] - a[0]); // Max heap based on value + + for (int i = 0; i < n; i++) { + //add current + maxHeap.offer(new int[]{nums[i], i}); + + // remove elements outside the current window + while (maxHeap.peek()[1] <= i - k) { + maxHeap.poll(); + } + + // Store the max for the current window + if (i >= k - 1) { + result[i - k + 1] = maxHeap.peek()[0]; + } + } + + return result; + } + + public static void main(String[] args) { + int[] nums = {1, 3, -1, -3, 5, 3, 6, 7}; + int k = 3; + System.out.println(Arrays.toString(maxSlidingWindow(nums, k))); + } +} diff --git a/src/main/java/com/thealgorithms/Heap/TaskScheduler.java b/src/main/java/com/thealgorithms/Heap/TaskScheduler.java new file mode 100644 index 000000000000..b3c628edbb47 --- /dev/null +++ b/src/main/java/com/thealgorithms/Heap/TaskScheduler.java @@ -0,0 +1,38 @@ +import java.util.*; + +public class TaskScheduler { + + public static int leastInterval(char[] tasks, int n) { + int[] freq = new int[26]; + for (char c : tasks) { + freq[c - 'A']++; + } + + Arrays.sort(freq); + int maxFreq = freq[25]; + int idleSlots = (maxFreq - 1) * n; + + // Fill idle slots with remaining tasks + for (int i = 24; i >= 0 && idleSlots > 0; i--) { + idleSlots -= Math.min(freq[i], maxFreq - 1); + } + + idleSlots = Math.max(0, idleSlots); + + return tasks.length + idleSlots; + } + + public static void main(String[] args) { + char[] tasks1 = {'A','A','A','B','B','B'}; + int n1 = 2; + System.out.println("Output 1: " + leastInterval(tasks1, n1)); // 8 + + char[] tasks2 = {'A','C','A','B','D','B'}; + int n2 = 1; + System.out.println("Output 2: " + leastInterval(tasks2, n2)); // 6 + + char[] tasks3 = {'A','A','A','B','B','B'}; + int n3 = 0; + System.out.println("Output 3: " + leastInterval(tasks3, n3)); // 6 + } +} diff --git a/src/main/java/com/thealgorithms/Heap/TopKFrequentElements.java b/src/main/java/com/thealgorithms/Heap/TopKFrequentElements.java new file mode 100644 index 000000000000..a4aa92be1392 --- /dev/null +++ b/src/main/java/com/thealgorithms/Heap/TopKFrequentElements.java @@ -0,0 +1,39 @@ +import java.util.*; + +public class TopKFrequentElements { + + public static int[] topKFrequent(int[] nums, int k) { + // Step 1: Count frequencies + Map freqMap = new HashMap<>(); + for (int num : nums) { + freqMap.put(num, freqMap.getOrDefault(num, 0) + 1); + } + + // Step 2: Use a min-heap to keep top k elements + PriorityQueue> minHeap = + new PriorityQueue<>((a, b) -> a.getValue() - b.getValue()); + + for (Map.Entry entry : freqMap.entrySet()) { + minHeap.offer(entry); + if (minHeap.size() > k) { + minHeap.poll(); // remove least frequent element + } + } + + // Step 3: Extract elements from heap + int[] result = new int[k]; + for (int i = k - 1; i >= 0; i--) { + result[i] = minHeap.poll().getKey(); + } + + return result; + } + + public static void main(String[] args) { + int[] nums = {1, 1, 1, 2, 2, 3, 3, 3, 3, 4}; + int k = 2; + + int[] res = topKFrequent(nums, k); + System.out.println("Top " + k + " frequent elements: " + Arrays.toString(res)); + } +}