Assignment 4-A

Stacks & Queues Implementation

Build complete stack and queue implementations from scratch using arrays and linked lists, then solve classic problems including balanced parentheses, expression evaluation, sliding window maximum, and more.

5-7 hours
Intermediate
150 Points
Submit Assignment
What You'll Practice
  • Stack using arrays & linked lists
  • Queue implementations
  • Expression evaluation
  • Monotonic stack/queue
  • Sliding window problems
Contents
01

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.

Format: Create a Java project with your implementations and problem solutions. Include a Main.java file that demonstrates and tests all your implementations.
Important: You must implement your own Stack and Queue classes. Do NOT use Java's built-in Stack, Queue, Deque, or ArrayDeque classes.
Skills Applied: This assignment tests your understanding of Stacks (Topic 4.1) and Queues (Topic 4.2) from Module 4.
Stacks (4.1)

LIFO principle, push/pop operations, expression evaluation, parentheses matching

Queues (4.2)

FIFO principle, circular queues, priority queues, sliding window

Ready to submit? Already completed the assignment? Submit your work now!
Submit Now
02

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
03

Part 1: Data Structure Implementation (60 Points)

Implement complete stack and queue data structures with all essential operations.

P1
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 EmptyStackException for pop/peek on empty stack
  • Use generics for type safety
P2
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)
}
P3
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
P4
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)
}
04

Part 2: Classic Problems (90 Points)

Solve these classic stack and queue problems. Create a class StackQueueProblems.java containing all solutions.

P5
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);
P6
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);
P7
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);
P8
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)
}
P9
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);
P10
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)
}
05

Submission

Create a public GitHub repository with the exact name shown below:

Required Repository Name
java-stacks-queues-dsa
github.com/<your-username>/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
Important: Test your implementations thoroughly with edge cases: empty structures, single element, full capacity, and boundary conditions. Make sure your code compiles with javac src/**/*.java.
Submit Your Assignment

Enter your GitHub username - we'll verify your repository automatically

06

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 Assignment
07

What 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

08

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