Algorithms and Problem Solving with Java
Heaps and `PriorityQueue
আপনি একটি free preview lesson দেখছেন।
Lesson Overview
আগের lesson-এ আমরা worklist হিসেবে ব্যবহার করেছি:
Queue
Stack
Deque
Queue বলে:
Oldest pending item first
Stack বলে:
Newest pending item first
কিন্তু কিছু problem-এ আমরা চাই:
Most important item first
Example:
Critical task
High priority task
Normal task
Low priority task
এখানে arrival order সবসময় main concern নয়।
আমাদের দরকার:
Priority-based processing
Java-তে এর জন্য গুরুত্বপূর্ণ abstraction হলো:
PriorityQueue<E>
এর ভিতরের core data-structure idea হলো:
Heap
এই lesson-এ আমরা শিখব:
- What priority-based processing means
- What a heap is
- Complete binary tree intuition
- Min Heap
- Max Heap
- Heap property
- Heap stored inside an array
- Parent and child indexes
- Heap insertion
- Heapify up
- Heap removal
- Heapify down
- Heap complexity
- Java
PriorityQueue - Default min-priority behavior
- Max-priority queues
offer()poll()peek()- Custom objects with Comparator
- Priority scheduling
- Top-K problems
- Common mistakes
Why FIFO Is Not Always Enough
Suppose support tickets arrive:
Ticket A → NORMAL
Ticket B → CRITICAL
Ticket C → LOW
A normal FIFO Queue processes:
A
B
C
But the business rule may require:
CRITICAL first
then NORMAL
then LOW
So desired order:
B
A
C
This is not FIFO।
It is:
Priority ordering
What Is a Priority Queue?
A priority queue stores multiple values but removes the value considered:
highest priority
or:
lowest priority
according to an ordering rule।
It does not primarily answer:
Which item arrived first?
Instead:
Which item should be processed next
according to priority?
Java PriorityQueue
Java provides:
java.util.PriorityQueue
Example:
PriorityQueue<Integer> numbers =
new PriorityQueue<>();
By default, smaller values have higher priority।
So:
numbers.offer(
30
);
numbers.offer(
10
);
numbers.offer(
20
);
Then:
numbers.poll();
returns:
10
Important Difference from FIFO Queue
Insertion order:
30
10
20
Removal order:
10
20
30
because priority is based on natural numeric ordering।
Basic Example
import java.util.PriorityQueue;
public class Main {
public static void main(String[] args) {
PriorityQueue<Integer> numbers =
new PriorityQueue<>();
numbers.offer(
30
);
numbers.offer(
10
);
numbers.offer(
20
);
while (
!numbers.isEmpty()
) {
System.out.println(
numbers.poll()
);
}
}
}
Output:
10
20
30
What Is a Heap?
A Heap is a tree-based data structure designed to efficiently maintain access to an extreme value such as:
minimum
or:
maximum
Two common types:
Min Heap
Max Heap
Min Heap
In a Min Heap:
Every parent is <= its children
Example:
10
/ \
20 30
/ \
40 50
The smallest value is always at the root:
10
Max Heap
In a Max Heap:
Every parent is >= its children
Example:
50
/ \
40 30
/ \
10 20
The largest value is at the root:
50
Heap Is Not Fully Sorted
This is extremely important।
Consider Min Heap:
10
/ \
20 15
/ \
40 30
This is valid because:
10 <= 20
10 <= 15
20 <= 40
20 <= 30
But notice:
15
is less than:
20
even though it appears in another branch।
A heap guarantees:
parent-child ordering
not:
complete global sorted order
Heap Property
For a Min Heap:
parent <= children
For a Max Heap:
parent >= children
That local property is enough to guarantee that the root contains the minimum or maximum value।
Complete Binary Tree
Heaps are commonly represented as:
Complete Binary Trees
A complete binary tree fills levels from:
top to bottom
and:
left to right
before starting a new level।
Example:
10
/ \
20 30
/ \ /
40 50 60
This is complete।
Why Completeness Matters
Because a complete binary tree can be stored efficiently inside an array without explicit child references।
Example heap:
10
/ \
20 30
/ \ /
40 50 60
Array representation:
[10, 20, 30, 40, 50, 60]
Heap Stored in an Array
Using zero-based indexing:
Index: 0 1 2 3 4 5
Value: 10 20 30 40 50 60
Tree:
10(0)
/ \
20(1) 30(2)
/ \ /
40(3) 50(4) 60(5)
Parent and Child Index Formulas
For index:
i
left child:
2 * i + 1
right child:
2 * i + 2
parent:
(i - 1) / 2
using integer division।
Example
For index:
1
left child:
2 * 1 + 1
= 3
right child:
2 * 1 + 2
= 4
Parent of index 4:
(4 - 1) / 2
= 3 / 2
= 1
Why Array Representation Is Useful
We do not need each heap node to store:
left reference
right reference
parent reference
The structure is implied by indexes।
That gives compact storage and good locality।
Heap Height
Because the tree remains complete, its height is approximately:
log₂ n
This is why inserting and removing from a heap can be:
O(log n)
Min Heap Insertion
Suppose heap:
10
/ \
20 30
/
40
Array:
[10, 20, 30, 40]
Insert:
15
First place it at the next available position:
10
/ \
20 30
/ \
40 15
But:
15 < 20
so Min Heap property is violated।
Heapify Up
Swap 15 with its parent:
10
/ \
15 30
/ \
40 20
Now:
10 <= 15
15 <= 40
15 <= 20
Heap property restored।
This upward repair process is often called:
heapify up
or:
sift up
Insertion Process
General Min Heap insertion:
1. Add new value at the end.
2. Compare with parent.
3. If smaller than parent, swap.
4. Continue upward.
5. Stop when heap property is satisfied.
Why Insertion Is O(log n)
The new value moves only upward through the tree height।
Heap height:
O(log n)
Therefore insertion:
O(log n)
Removing the Minimum
In a Min Heap, the minimum is at the root।
Suppose:
10
/ \
20 30
/ \
40 50
We want to remove:
10
If we simply remove the root, we leave a hole।
Replace Root with Last Value
Take last value:
50
Move it to root:
50
/ \
20 30
/
40
Now heap property is violated।
Heapify Down
Compare:
50
with children:
20
30
Choose smaller child:
20
Swap:
20
/ \
50 30
/
40
Still:
50 > 40
Swap again:
20
/ \
40 30
/
50
Heap restored।
Removal Process
General Min Heap removal:
1. Save root.
2. Move last element to root.
3. Remove last slot.
4. Compare root with children.
5. Swap with smaller child if necessary.
6. Continue downward.
This is:
heapify down
or:
sift down
Removal Complexity
The value may travel from root to leaf।
Tree height:
O(log n)
Therefore removal:
O(log n)
Inspecting the Root
The root is stored at index:
0
So reading the minimum or maximum value is:
O(1)
This is one of the most important heap properties।
Heap Complexity Summary
For a typical binary heap:
Peek root:
O(1)
Insert:
O(log n)
Remove root:
O(log n)
Compare with Sorted List
Suppose we keep a normal array fully sorted।
Finding minimum:
O(1)
But inserting into the correct middle position may require shifting many values:
O(n)
Heap allows efficient insertion:
O(log n)
while still providing immediate root access।
Heap Tradeoff
A heap is excellent when the primary requirement is:
Repeatedly get the next minimum/maximum
while values are being added and removed.
It is not designed for:
Fast arbitrary search
or:
Fully sorted traversal without removals
Java PriorityQueue
Java's PriorityQueue uses heap-based semantics।
Default:
PriorityQueue<Integer> queue =
new PriorityQueue<>();
behaves as a:
Min Priority Queue
for natural numeric ordering।
Core Operations
offer(...)
poll()
peek()
Same names we learned with Queue।
But removal order now follows:
priority
instead of:
arrival order
offer()
queue.offer(
30
);
Insertion is typically:
O(log n)
peek()
Integer next =
queue.peek();
returns the current highest-priority element without removing it।
For default integer ordering:
smallest value
Complexity:
O(1)
poll()
Integer next =
queue.poll();
removes the highest-priority element।
Typical complexity:
O(log n)
Empty PriorityQueue
Like Queue:
peek()
returns:
null
when empty।
And:
poll()
returns:
null
when empty।
remove() and element()
The exception-based alternatives also exist:
remove()
element()
On empty queue they throw:
NoSuchElementException
For normal processing loops:
poll()
peek()
are often simpler।
Default Min Priority
Example:
PriorityQueue<Integer> scores =
new PriorityQueue<>();
scores.offer(
90
);
scores.offer(
60
);
scores.offer(
80
);
scores.offer(
70
);
Poll sequence:
60
70
80
90
PriorityQueue Iteration Is Not Sorted Traversal
This is a critical rule।
Suppose:
PriorityQueue<Integer> queue =
new PriorityQueue<>();
queue.offer(
30
);
queue.offer(
10
);
queue.offer(
20
);
This:
for (
int value
: queue
) {
System.out.println(
value
);
}
is not guaranteed to produce:
10
20
30
Heap internal iteration order is not the same as repeated priority removal order।
To Get Priority Order
Use:
while (
!queue.isEmpty()
) {
System.out.println(
queue.poll()
);
}
This consumes the queue and returns values according to priority।
Preserve the PriorityQueue
If you need priority-order output but must preserve the original queue:
PriorityQueue<Integer> copy =
new PriorityQueue<>(
queue
);
Then poll from:
copy
Max Priority Queue
Suppose larger integers should come first।
We need a Max Heap-like ordering।
Use:
PriorityQueue<Integer> queue =
new PriorityQueue<>(
Comparator.reverseOrder()
);
Max Priority Example
PriorityQueue<Integer> queue =
new PriorityQueue<>(
Comparator.reverseOrder()
);
queue.offer(
30
);
queue.offer(
10
);
queue.offer(
20
);
Poll order:
30
20
10
Priority Is Defined by Comparator
A useful way to think:
Comparator decides
which value belongs at the front.
The value considered "smallest" according to the comparator becomes:
peek()
and:
poll()
result।
PriorityQueue of Objects
Suppose:
record Task(
long id,
String description,
int priority
) {
}
We want smaller priority number to mean more urgent:
1 → CRITICAL
2 → HIGH
3 → NORMAL
4 → LOW
Custom Comparator
PriorityQueue<Task> tasks =
new PriorityQueue<>(
Comparator.comparingInt(
Task::priority
)
);
Example
tasks.offer(
new Task(
1,
"Generate report",
3
)
);
tasks.offer(
new Task(
2,
"Fix production outage",
1
)
);
tasks.offer(
new Task(
3,
"Send email",
4
)
);
Poll order:
Fix production outage
Generate report
Send email
Complete Example
import java.util.Comparator;
import java.util.PriorityQueue;
public class Main {
public static void main(String[] args) {
PriorityQueue<Task> tasks =
new PriorityQueue<>(
Comparator.comparingInt(
Task::priority
)
);
tasks.offer(
new Task(
1,
"Generate report",
3
)
);
tasks.offer(
new Task(
2,
"Fix production outage",
1
)
);
tasks.offer(
new Task(
3,
"Send welcome email",
4
)
);
tasks.offer(
new Task(
4,
"Investigate failed payment",
2
)
);
while (
!tasks.isEmpty()
) {
Task task =
tasks.poll();
System.out.println(
task.priority()
+ " - "
+ task.description()
);
}
}
record Task(
long id,
String description,
int priority
) {
}
}
Output:
1 - Fix production outage
2 - Investigate failed payment
3 - Generate report
4 - Send welcome email
Equal Priorities
Suppose two tasks both have:
priority = 1
Does PriorityQueue guarantee FIFO between them?
Do not assume so।
If equal-priority processing order matters, include a tie-breaker।
Tie-Breaker Comparator
Suppose:
record Task(
long sequence,
String description,
int priority
) {
}
Use:
Comparator<Task> ordering =
Comparator.comparingInt(
Task::priority
).thenComparingLong(
Task::sequence
);
Now:
lower priority number first
then earlier sequence first
Why Tie-Breakers Matter
Without an explicit secondary ordering:
Equal priority values
may come out in an order you should not depend on।
If business rules require:
Critical first
and among critical tasks FIFO
encode both rules।
Priority Enum
Instead of raw numbers, a domain may use:
enum Priority {
CRITICAL,
HIGH,
NORMAL,
LOW
}
Enum natural ordering follows declaration order।
So:
Comparator.comparing(
Task::priority
)
would prioritize:
CRITICAL
HIGH
NORMAL
LOW
if declared in that order।
Example with Enum
enum Priority {
CRITICAL,
HIGH,
NORMAL,
LOW
}
Task:
record Task(
long sequence,
String description,
Priority priority
) {
}
Comparator:
Comparator<Task> ordering =
Comparator.comparing(
Task::priority
).thenComparingLong(
Task::sequence
);
This is clearer than magic numbers such as:
1
2
3
4
Priority Queue Is Not a Sorted List
This distinction is essential।
A PriorityQueue guarantees:
The next highest-priority item
is available efficiently.
It does not guarantee:
Every element is stored in globally sorted sequence.
When to Use PriorityQueue
Use it when the recurring operation is:
Add item
Get best-priority item
Remove best-priority item
Repeat
Examples:
Job scheduling
Event simulation
Top-K tracking
Shortest-path algorithms
Merging sorted streams
Task prioritization
When Not to Use PriorityQueue
If you need:
Fast search by ID
use something like:
Map
If you need:
Unique membership
use:
Set
If you need:
Fully sorted random-access list
a sorted collection/list approach may be more appropriate।
Searching a PriorityQueue
Suppose:
queue.contains(
value
);
A heap is not optimized for arbitrary lookup।
contains() may require scanning values:
O(n)
Do not confuse:
fast access to root
with:
fast access to every value
Removing an Arbitrary Value
Removing:
queue.poll()
removes the root efficiently:
O(log n)
But removing a specific arbitrary object may first require locating it:
O(n)
and then repairing the heap।
So PriorityQueue is optimized around:
the head
not arbitrary positions।
Top-K Problems
A very common heap use case is:
Keep the K largest or smallest values
while processing many values.
Suppose we have millions of scores but only need:
Top 3
We do not necessarily need to sort every value।
Top 3 Largest Values
We can maintain a Min Heap of at most:
3 values
Why Min Heap?
Because among the current top 3, we need fast access to:
the smallest of those top 3
so we can replace it when a better candidate arrives।
Example Algorithm
Values:
10
90
50
80
100
70
Keep heap size:
3
Process each value:
Add value
If heap size > 3:
remove smallest
At the end, the heap contains the three largest values।
Top-K Implementation
static PriorityQueue<Integer> topLargest(
int[] values,
int k
) {
if (
k <= 0
) {
throw new IllegalArgumentException(
"k must be positive."
);
}
PriorityQueue<Integer> heap =
new PriorityQueue<>();
for (
int value
: values
) {
heap.offer(
value
);
if (
heap.size() > k
) {
heap.poll();
}
}
return heap;
}
Why This Works
Suppose heap contains:
70
90
100
The root is:
70
which is the weakest member of the current top three।
If new value:
80
arrives:
70
80
90
100
Remove minimum:
70
Remaining:
80
90
100
Exactly the new top three।
Top-K Complexity
For each of n values:
offer into heap of size at most k
cost:
O(log k)
Possibly:
poll
also:
O(log k)
Total:
O(n log k)
Space:
O(k)
Compare with Full Sorting
Sort all n values:
O(n log n)
then take top k।
Heap approach:
O(n log k)
When:
k << n
this can be much more efficient।
Example
Suppose:
n = 10,000,000
k = 10
A heap only stores:
10 values
while scanning the entire dataset।
This is a very useful streaming-style technique।
Top K Smallest
To keep the k smallest values, use a Max Heap of size k।
Why?
Because among the current smallest k, you want the largest candidate at the root so it can be removed when a better smaller value arrives।
Max Heap for K Smallest
PriorityQueue<Integer> heap =
new PriorityQueue<>(
Comparator.reverseOrder()
);
Process:
heap.offer(
value
);
if (
heap.size() > k
) {
heap.poll();
}
Now the heap retains the smallest k values।
Choosing Min Heap vs Max Heap for Top-K
This often confuses beginners।
Remember:
Need K largest
→ maintain Min Heap of size K
Need K smallest
→ maintain Max Heap of size K
Why?
Because the root should be:
the easiest current candidate to discard.
Priority Scheduling
Suppose a worker processes:
CRITICAL
HIGH
NORMAL
LOW
A PriorityQueue is a natural in-memory scheduling structure।
But real distributed job processing introduces additional concerns:
Durability
Concurrency
Retries
Fairness
Starvation
Multiple consumers
Persistence
A Java PriorityQueue alone does not solve these।
Starvation
Priority scheduling can create a problem।
Suppose high-priority tasks arrive continuously।
Low-priority tasks may wait indefinitely।
This is called:
starvation
Priority algorithms often need fairness rules such as:
aging
quotas
priority adjustment
depending on the system।
Heap Sort Connection
A heap can also be used to sort data।
Conceptually:
Build heap
Repeatedly remove root
If using a Min Heap:
poll repeatedly
produces ascending order।
PriorityQueue-Based Sort
static int[] heapSortedCopy(
int[] values
) {
PriorityQueue<Integer> queue =
new PriorityQueue<>();
for (
int value
: values
) {
queue.offer(
value
);
}
int[] result =
new int[
values.length
];
for (
int i = 0;
i < result.length;
i++
) {
result[i] =
queue.poll();
}
return result;
}
Complexity
Insert n values individually:
O(n log n)
Poll n values:
O(n log n)
Overall:
O(n log n)
Extra space:
O(n)
Is This Java's Heap Sort?
Not exactly।
This demonstrates heap-based sorting using PriorityQueue, but a traditional in-place Heap Sort works directly inside an array and has different space characteristics।
We do not need to implement full Heap Sort in this course।
Building a Heap
A heap can be built from existing data more efficiently than inserting each value one by one using specialized heap-construction techniques।
That operation can be:
O(n)
rather than:
O(n log n)
for repeated insertion।
This is a deeper heap detail。
For now, understand that heap construction can be optimized beyond naive repeated insertion।
Heap Is Not a Binary Search Tree
Both are trees, but their guarantees are different।
Heap:
Parent-child priority relationship
Binary Search Tree:
Left values ordered relative to node
Right values ordered relative to node
A heap is optimized for:
minimum/maximum access
A Binary Search Tree is designed for different searching and ordering operations।
We'll study BST fundamentals later।
Heap vs Sorted Array
Heap
peek best:
O(1)
insert:
O(log n)
remove best:
O(log n)
arbitrary search:
O(n)
Sorted Array
binary search:
O(log n)
best element:
O(1)
insert while preserving sort:
O(n)
Different structures optimize different operations।
Heap vs HashMap
Heap:
What is highest-priority item?
HashMap:
What value belongs to this key?
Do not choose one based only on which complexity sounds faster।
They solve different access problems।
Heap vs Queue
Queue:
Arrival order
PriorityQueue:
Priority order
Example:
Arrival:
A(priority 5)
B(priority 1)
C(priority 3)
FIFO Queue:
A
B
C
PriorityQueue:
B
C
A
assuming smaller number means higher priority।
Heap vs Stack
Stack:
Most recently added first
PriorityQueue:
Best according to comparator first
Again, different processing policies।
PriorityQueue and Null
PriorityQueue does not permit:
null
Do not insert null values।
Priority comparison requires meaningful elements।
Mutable Priority Fields Are Dangerous
Suppose:
record Task(
...
)
is replaced by a mutable class and you change its priority after insertion।
Example conceptually:
Task inserted with priority 5
↓
priority changed to 1
The PriorityQueue does not automatically know that its heap ordering must be repaired।
Important Rule
Do not mutate fields that affect ordering while an object is stored inside a PriorityQueue।
Safer approach:
Remove object
Change ordering field
Insert again
or use immutable queued values।
Comparator Must Be Consistent Enough
A comparator should define predictable ordering।
Bad comparator behavior such as:
A < B
B < C
C < A
can make sorting and priority behavior unreliable।
Comparators should follow a coherent ordering contract।
Common Mistake 1 — Expecting FIFO
PriorityQueue is not a normal FIFO Queue।
Insertion order does not determine processing order।
Common Mistake 2 — Thinking Iteration Is Sorted
This:
for (
T value
: priorityQueue
)
does not guarantee priority-sorted traversal।
Use repeated:
poll()
for priority order।
Common Mistake 3 — Forgetting Default Is Min Priority
new PriorityQueue<Integer>()
returns smaller numbers first।
If larger number means higher priority, use:
Comparator.reverseOrder()
Common Mistake 4 — Equal Priority Without Tie-Breaker
If equal-priority FIFO behavior matters, encode arrival sequence explicitly।
Do not rely on unspecified ordering।
Common Mistake 5 — Using PriorityQueue for Arbitrary Search
The root is fast।
Searching arbitrary elements is not।
Use the data structure that matches the access pattern।
Common Mistake 6 — Thinking Heap Is Fully Sorted
Only the root and parent-child relationships are guaranteed।
Internal representation is not a sorted sequence।
Common Mistake 7 — Mutating Priority After Insertion
Changing ordering fields while an item remains inside the PriorityQueue can invalidate expected ordering behavior।
Common Mistake 8 — Wrong Heap for Top-K
Remember:
K largest
→ Min Heap size K
K smallest
→ Max Heap size K
Common Mistake 9 — Treating Priority as Complete Scheduling
A PriorityQueue solves in-memory ordering।
It does not automatically solve:
Retries
Persistence
Concurrency
Distributed ownership
Fairness
Common Mistake 10 — Ignoring Starvation
Always processing highest priority can leave low-priority work waiting indefinitely।
Priority systems may need fairness policies।
Practical Example — Priority Enrollment Review
import java.util.Comparator;
import java.util.PriorityQueue;
public class Main {
public static void main(String[] args) {
PriorityQueue<ReviewRequest> requests =
new PriorityQueue<>(
Comparator.comparing(
ReviewRequest::priority
).thenComparingLong(
ReviewRequest::sequence
)
);
requests.offer(
new ReviewRequest(
1,
"Sakib",
Priority.NORMAL
)
);
requests.offer(
new ReviewRequest(
2,
"Subu",
Priority.CRITICAL
)
);
requests.offer(
new ReviewRequest(
3,
"Sumu",
Priority.HIGH
)
);
requests.offer(
new ReviewRequest(
4,
"Nur",
Priority.CRITICAL
)
);
while (
!requests.isEmpty()
) {
ReviewRequest request =
requests.poll();
System.out.println(
request.priority()
+ " - "
+ request.learner()
);
}
}
enum Priority {
CRITICAL,
HIGH,
NORMAL,
LOW
}
record ReviewRequest(
long sequence,
String learner,
Priority priority
) {
}
}
Output:
CRITICAL - Subu
CRITICAL - Nur
HIGH - Sumu
NORMAL - Sakib
Among equal CRITICAL requests:
sequence
preserves the intended order।
Practice 1 — Default PriorityQueue
Given:
PriorityQueue<Integer> queue =
new PriorityQueue<>();
queue.offer(
30
);
queue.offer(
10
);
queue.offer(
20
);
What does:
queue.peek()
return?
Answer
10
Practice 2 — Poll Order
For the same queue, repeated poll() returns:
Answer
10
20
30
Practice 3 — Max PriorityQueue
Create a PriorityQueue where larger integers come first।
Solution
PriorityQueue<Integer> queue =
new PriorityQueue<>(
Comparator.reverseOrder()
);
Practice 4 — Heap Property
Is this a valid Min Heap?
5
/ \
10 8
/ \
20 15
Answer
Yes।
Every parent is less than or equal to its children।
Practice 5 — Not Fully Sorted
Is this valid Min Heap?
5
/ \
20 10
Answer
Yes।
The structure does not require:
20 <= 10
because they are siblings।
Only parent-child relationships matter।
Practice 6 — Complexity
Heap root inspection:
?
Answer
O(1)
Practice 7 — Complexity
Heap insertion:
?
Answer
O(log n)
Practice 8 — Complexity
Removing heap root:
?
Answer
O(log n)
Practice 9 — Top 10 Largest
Which bounded heap should be maintained?
Answer
Min Heap of size 10
because the smallest member of the current top 10 should be easiest to discard।
Practice 10 — Top 10 Smallest
Which heap?
Answer
Max Heap of size 10
Practice 11 — Equal Priority
Two tasks have the same priority and FIFO ordering between them matters।
What should you add?
Answer
A secondary ordering such as:
sequence number
creation time
and include it with:
thenComparing(...)
Practice 12 — Choose Structure
Need:
Fast ID → Course lookup
PriorityQueue or HashMap?
Answer
HashMap
PriorityQueue is designed around priority access, not key lookup।
Practice 13 — Iteration
Does iterating a PriorityQueue guarantee sorted output?
Answer
No।
Practice 14 — Mutation
Why is changing a queued object's priority dangerous?
Answer
Because the queue's internal heap structure was built using the old ordering value and is not automatically repaired after arbitrary field mutation।
True or False
- PriorityQueue always follows FIFO.
- Java's default
PriorityQueue<Integer>returns smaller values first. - A heap is always globally sorted.
- A Min Heap keeps its minimum at the root.
- A Max Heap keeps its maximum at the root.
- Heap insertion is typically
O(log n). - Heap root inspection is
O(1). - Heap root removal is typically
O(log n). - Iterating a PriorityQueue guarantees priority order.
poll()removes the current priority head.Comparator.reverseOrder()can create max-style integer priority.- PriorityQueue allows
null. - Top-K problems are a common heap use case.
- K largest values can be maintained using a Min Heap of size K.
- Arbitrary PriorityQueue search is optimized to
O(log n).
Answers
1. False
2. True
3. False
4. True
5. True
6. True
7. True
8. True
9. False
10. True
11. True
12. False
13. True
14. True
15. False
Knowledge Check
Question 1
What problem does a PriorityQueue solve?
Question 2
What is a Min Heap?
Question 3
What is a Max Heap?
Question 4
Why does a heap not need to be completely sorted?
Question 5
Why can heap insertion be O(log n)?
Question 6
How is the root removed while preserving the complete-tree structure?
Question 7
What is heapify up?
Question 8
What is heapify down?
Question 9
What does Java's default PriorityQueue<Integer> prioritize?
Question 10
Why is PriorityQueue iteration not necessarily sorted?
Question 11
Why is a Min Heap useful for finding the K largest values?
Question 12
Why should ordering fields generally remain unchanged while an item is inside a PriorityQueue?
Knowledge Check Answers
Answer 1
A PriorityQueue efficiently stores pending items and provides access to the next item according to an ordering or priority rule rather than simple arrival order।
Answer 2
A Min Heap is a complete binary tree where each parent is less than or equal to its children, making the minimum value available at the root।
Answer 3
A Max Heap is a complete binary tree where each parent is greater than or equal to its children, making the maximum value available at the root।
Answer 4
The primary requirement is only that the best-priority value stays at the root and that parent-child heap relationships remain valid. Full global ordering would require unnecessary additional work।
Answer 5
A new element is added at the bottom and can move upward only along one path whose length is proportional to the heap height:
O(log n)
Answer 6
The root is saved, the final heap element is moved into the root position, the last slot is removed, and the replacement value is moved downward until heap order is restored।
Answer 7
Heapify up moves a newly inserted element upward by comparing and swapping with its parent until the heap property is restored।
Answer 8
Heapify down moves a replacement root downward by comparing and swapping with the appropriate child until heap order is restored।
Answer 9
Natural ascending ordering, so the smallest integer has the highest removal priority।
Answer 10
The heap only guarantees the priority element at the root and valid parent-child relationships. Its internal array is not a fully sorted representation।
Answer 11
The heap stores only K candidates, and its root represents the smallest value among the current K largest. A new larger candidate can replace that weakest member efficiently।
Answer 12
Because PriorityQueue does not automatically reorganize itself when an object's comparison-relevant state changes after insertion।
Practical Decision Guide
Use:
Queue
when:
Oldest work should be processed first.
Use:
Deque as Stack
when:
Newest work should be processed first.
Use:
PriorityQueue
when:
Best-priority work should be processed first.
Use:
HashMap
when:
Lookup by key is the main operation.
Use:
HashSet
when:
Fast membership checking is the main operation.
Heap Complexity Cheat Sheet
For a binary heap:
peek root
→ O(1)
insert
→ O(log n)
remove root
→ O(log n)
arbitrary search
→ O(n)
Top-K with a bounded heap:
Time
→ O(n log k)
Space
→ O(k)
Core Mental Model
A Queue asks:
Who arrived first?
A Stack asks:
Who arrived last?
A PriorityQueue asks:
Who is most important according
to the ordering rule?
And a Heap makes that last question efficient by maintaining:
the best-priority value at the root
without fully sorting everything.
Lesson Summary
এই lesson-এ আমরা heap এবং priority-based processing-এর foundation শিখেছি।
We learned:
- PriorityQueue processes according to priority rather than arrival order
- A heap is a complete binary tree with a parent-child ordering property
- Min Heap keeps the minimum at the root
- Max Heap keeps the maximum at the root
- A heap is not globally sorted
- Complete binary trees can be efficiently stored in arrays
- Parent and child positions can be calculated from indexes
- Insertion adds at the end and uses heapify up
- Root removal replaces the root with the last value and uses heapify down
- Heap root access is
O(1) - Heap insertion and root removal are
O(log n) - Java's
PriorityQueueuses heap-style priority semantics - Default
PriorityQueue<Integer>returns smaller values first - Max-style priority can be created with a reversed comparator
- Custom objects can use
Comparator - Equal-priority ordering should use an explicit tie-breaker when required
- PriorityQueue iteration is not guaranteed to be sorted
- Arbitrary lookup is not what a heap optimizes
- Top-K problems can be solved efficiently with bounded heaps
- K largest typically uses a Min Heap of size K
- K smallest typically uses a Max Heap of size K
- Mutable priority fields can break expected queue ordering
- Priority scheduling may need fairness rules to avoid starvation
The central heap idea is:
Do not fully sort everything.
Maintain just enough structure
to know which item should come next.
Next Lesson
পরবর্তী lesson:
Hashing and Fast Lookup
আমরা শিখব:
- What hashing means
- Hash functions
- Hash tables
- Buckets
- Collisions
HashMapHashSet- Average
O(1)lookup - Worst-case intuition
- Load factor and resizing intuition
equals()andhashCode()- Why equal objects need equal hash codes
- Mutable keys
- Hash-based duplicate detection
- Fast membership and key-based lookup
- When hashing is better than linear or binary search