Assignment Overview
In this assignment, you will implement complete stack and queue data structures from scratch using both arrays and linked lists, then solve 10 classic problems that demonstrate the power of these fundamental data structures.
Main.java file that demonstrates and tests all your implementations.
Stack, Queue, Deque, or ArrayDeque classes.
Stacks (4.1)
LIFO principle, push/pop operations, expression evaluation, parentheses matching
Queues (4.2)
FIFO principle, circular queues, priority queues, sliding window
Topics Covered
4.1 Stacks
- Stack operations - push, pop, peek, isEmpty, size
- Array-based implementation - dynamic resizing
- Linked list implementation - O(1) operations
- Applications - expression evaluation, undo/redo
4.2 Queues
- Queue operations - enqueue, dequeue, front, isEmpty
- Circular queue - efficient array-based queue
- Deque (Double-ended queue) - operations at both ends
- Priority queue basics - ordering by priority
Part 1: Data Structure Implementation (60 Points)
Implement complete stack and queue data structures with all essential operations.
Array-Based Stack (15 points)
Create a class ArrayStack.java with dynamic resizing:
public class ArrayStack<T> {
private T[] array;
private int top;
private static final int DEFAULT_CAPACITY = 10;
public ArrayStack(); // Default capacity
public ArrayStack(int capacity); // Custom capacity
public void push(T item); // O(1) amortized
public T pop(); // O(1)
public T peek(); // O(1)
public boolean isEmpty(); // O(1)
public int size(); // O(1)
public void clear(); // O(1)
// Dynamic resizing
private void resize(int newCapacity);
}
Requirements:
- Double capacity when full, halve when 1/4 full
- Throw
EmptyStackExceptionfor pop/peek on empty stack - Use generics for type safety
Linked List Stack (15 points)
Create a class LinkedStack.java:
public class LinkedStack<T> {
private class Node {
T data;
Node next;
Node(T data) { this.data = data; }
}
private Node top;
private int size;
public void push(T item); // O(1)
public T pop(); // O(1)
public T peek(); // O(1)
public boolean isEmpty(); // O(1)
public int size(); // O(1)
public void clear(); // O(1)
}
Circular Queue (15 points)
Create a class CircularQueue.java with fixed capacity:
public class CircularQueue<T> {
private T[] array;
private int front;
private int rear;
private int size;
private int capacity;
public CircularQueue(int capacity);
public void enqueue(T item); // O(1) - throws if full
public T dequeue(); // O(1) - throws if empty
public T front(); // O(1)
public T rear(); // O(1)
public boolean isEmpty(); // O(1)
public boolean isFull(); // O(1)
public int size(); // O(1)
}
// Example usage:
CircularQueue<Integer> queue = new CircularQueue<>(5);
queue.enqueue(1); // [1, _, _, _, _]
queue.enqueue(2); // [1, 2, _, _, _]
queue.dequeue(); // returns 1, [_, 2, _, _, _]
queue.enqueue(3); // [_, 2, 3, _, _]
// When rear reaches end, it wraps around to front
Deque (Double-Ended Queue) (15 points)
Create a class Deque.java supporting operations at both ends:
public class Deque<T> {
// Can use doubly linked list or circular array
public void addFirst(T item); // O(1)
public void addLast(T item); // O(1)
public T removeFirst(); // O(1)
public T removeLast(); // O(1)
public T peekFirst(); // O(1)
public T peekLast(); // O(1)
public boolean isEmpty(); // O(1)
public int size(); // O(1)
}
Part 2: Classic Problems (90 Points)
Solve these classic stack and queue problems. Create a class StackQueueProblems.java containing all solutions.
Balanced Parentheses (15 points)
Check if parentheses are balanced:
// P5a: Check if string has balanced parentheses (), [], {}
// "({[]})" → true
// "([)]" → false
// "{[]}" → true
public boolean isBalanced(String s);
// P5b: Find minimum insertions to make balanced
// "(((" → 3 (need 3 closing)
// "())" → 1 (need 1 opening)
// "(()))" → 1
public int minInsertions(String s);
// P5c: Remove minimum parentheses to make valid
// "()())()" → "()()()"
// "(a(b(c)d)" → "a(b(c)d)" or "(ab(c)d)"
public String removeInvalidParentheses(String s);
Expression Evaluation (15 points)
Evaluate mathematical expressions:
// P6a: Evaluate postfix expression
// "2 3 + 4 *" → 20 (i.e., (2+3)*4)
// "5 1 2 + 4 * + 3 -" → 14
public int evaluatePostfix(String expression);
// P6b: Convert infix to postfix
// "2 + 3 * 4" → "2 3 4 * +"
// "(2 + 3) * 4" → "2 3 + 4 *"
public String infixToPostfix(String expression);
// P6c: Evaluate infix expression with +, -, *, /, ()
// "2 + 3 * 4" → 14
// "(2 + 3) * 4" → 20
// "10 + 2 * 6" → 22
public int evaluateInfix(String expression);
Monotonic Stack Problems (15 points)
Use monotonic stacks for efficient solutions:
// P7a: Next Greater Element
// For each element, find the next greater element to its right
// [4, 5, 2, 25] → [5, 25, 25, -1]
// [13, 7, 6, 12] → [-1, 12, 12, -1]
public int[] nextGreaterElement(int[] arr);
// P7b: Daily Temperatures
// Days until a warmer temperature
// [73, 74, 75, 71, 69, 72, 76, 73] → [1, 1, 4, 2, 1, 1, 0, 0]
public int[] dailyTemperatures(int[] temperatures);
// P7c: Largest Rectangle in Histogram
// [2, 1, 5, 6, 2, 3] → 10 (rectangle of height 5, width 2)
public int largestRectangleInHistogram(int[] heights);
Stack Design Problems (15 points)
Implement special stack variants:
// P8a: Min Stack - O(1) getMin()
public class MinStack {
public void push(int val);
public void pop();
public int top();
public int getMin(); // O(1) - return minimum element
}
// P8b: Max Stack - O(1) getMax() and popMax()
public class MaxStack {
public void push(int val);
public int pop();
public int top();
public int peekMax();
public int popMax(); // Remove and return max element
}
// P8c: Stack with middle operations
public class MiddleStack {
public void push(int val);
public int pop();
public int getMiddle(); // O(1)
public int deleteMiddle(); // O(1)
}
Sliding Window Maximum (15 points)
Use deque for efficient sliding window:
// P9a: Maximum of each sliding window of size k
// [1, 3, -1, -3, 5, 3, 6, 7], k=3 → [3, 3, 5, 5, 6, 7]
// Window positions: [1,3,-1], [3,-1,-3], [-1,-3,5], [-3,5,3], [5,3,6], [3,6,7]
public int[] maxSlidingWindow(int[] nums, int k);
// P9b: Minimum of each sliding window of size k
// [1, 3, -1, -3, 5, 3, 6, 7], k=3 → [-1, -3, -3, -3, 3, 3]
public int[] minSlidingWindow(int[] nums, int k);
// P9c: First negative in each window of size k
// [12, -1, -7, 8, -15, 30, 16, 28], k=3 → [-1, -1, -7, -15, -15, 0]
public int[] firstNegativeInWindow(int[] nums, int k);
Queue Design & Applications (15 points)
Implement special queue variants:
// P10a: Implement Queue using Two Stacks
public class QueueUsingStacks<T> {
public void enqueue(T item); // O(1)
public T dequeue(); // O(1) amortized
public T peek();
public boolean isEmpty();
}
// P10b: Implement Stack using Two Queues
public class StackUsingQueues<T> {
public void push(T item);
public T pop();
public T top();
public boolean isEmpty();
}
// P10c: LRU Cache using Queue + HashMap
public class LRUCache {
public LRUCache(int capacity);
public int get(int key); // O(1)
public void put(int key, int value); // O(1)
}
Submission
Create a public GitHub repository with the exact name shown below:
Required Repository Name
java-stacks-queues-dsa
Required Files
java-stacks-queues-dsa/
├── src/
│ ├── datastructures/
│ │ ├── ArrayStack.java # P1
│ │ ├── LinkedStack.java # P2
│ │ ├── CircularQueue.java # P3
│ │ └── Deque.java # P4
│ ├── problems/
│ │ ├── StackQueueProblems.java # P5-P9
│ │ ├── MinStack.java # P8a
│ │ ├── MaxStack.java # P8b
│ │ ├── MiddleStack.java # P8c
│ │ ├── QueueUsingStacks.java # P10a
│ │ ├── StackUsingQueues.java # P10b
│ │ └── LRUCache.java # P10c
│ └── Main.java # Demo all solutions
├── test/
│ └── StackQueueTests.java # Optional: JUnit tests
└── README.md # REQUIRED
README.md Must Include:
- Your full name and submission date
- Time and space complexity for each method
- Explanation of monotonic stack approach for P7
- Instructions to compile and run the code
Do Include
- All 4 data structure implementations (P1-P4)
- All problem solutions (P5-P10)
- Main.java with comprehensive tests
- Time/space complexity in code comments
- Edge case handling
- Generics in implementations
Do Not Include
- Java's built-in Stack, Queue, Deque classes
- Any .class files (compiled bytecode)
- IDE-specific folders (.idea, .vscode)
- Solutions copied from online sources
- Code that doesn't compile
- Incomplete implementations
javac src/**/*.java.
Enter your GitHub username - we'll verify your repository automatically
Grading Rubric
Your assignment will be graded on the following criteria:
| Problem | Points | Key Criteria |
|---|---|---|
| P1: Array Stack | 15 | Dynamic resizing, O(1) amortized push |
| P2: Linked Stack | 15 | All O(1) operations, proper memory |
| P3: Circular Queue | 15 | Proper wrap-around, full/empty detection |
| P4: Deque | 15 | O(1) operations at both ends |
| P5: Balanced Parentheses | 15 | All bracket types, min insertions, removal |
| P6: Expression Evaluation | 15 | Postfix eval, infix conversion, operator precedence |
| P7: Monotonic Stack | 15 | O(n) solutions, histogram rectangle |
| P8: Special Stacks | 15 | O(1) getMin/getMax, middle operations |
| P9: Sliding Window | 15 | O(n) using deque, all window variants |
| P10: Queue Design | 15 | Stack↔Queue conversion, LRU Cache O(1) |
| Total | 150 |
Ready to Submit?
Make sure you have completed all implementations and reviewed the grading rubric above.
Submit Your AssignmentWhat You Will Practice
LIFO & FIFO Principles
Understanding when to use stacks vs queues based on access patterns
Monotonic Structures
Using monotonic stacks/queues for O(n) solutions to sliding window problems
Expression Parsing
Converting and evaluating mathematical expressions using stacks
Data Structure Design
Building complex structures like LRU Cache using basic building blocks
Pro Tips
Stack Tips
- For matching problems, push opening brackets, pop for closing
- Monotonic stack: maintain increasing/decreasing order
- Expression eval: operators go to operator stack, operands to value stack
- For min/max stack, use auxiliary stack to track extremes
Queue Tips
- Circular queue: use modulo for wrap-around
- Track size separately to distinguish full from empty
- Sliding window max: remove smaller elements from back
- Deque: doubly linked list gives O(1) at both ends
Expression Tips
- Operator precedence: * / before + -
- Left-to-right for same precedence
- Parentheses override all precedence
- Push '(' directly, pop until '(' for ')'
Common Pitfalls
- Off-by-one errors in circular queue indices
- Not handling empty stack/queue operations
- Forgetting to resize array when shrinking
- Infinite loop in circular structures