Assignment 3-A

Linked List Implementation

Build complete singly and doubly linked list implementations from scratch, then solve classic linked list problems including cycle detection, reversal, merging, and complex pointer manipulation challenges.

5-7 hours
Intermediate
150 Points
Submit Assignment
What You'll Practice
  • Node class design
  • Singly & doubly linked lists
  • Fast and slow pointer technique
  • Cycle detection algorithms
  • List reversal and merging
Contents
01

Assignment Overview

In this assignment, you will implement complete linked list data structures from scratch and solve 8 classic linked list problems. This is a hands-on coding assignment that tests your understanding of pointer manipulation, node-based structures, and algorithmic thinking.

Format: Create a Java project with your linked list implementations and problem solutions. Include a Main.java file that demonstrates and tests all your implementations.
Important: You must implement your own linked list classes. Do NOT use Java's built-in LinkedList class. The goal is to understand the internal workings of linked structures.
Skills Applied: This assignment tests your understanding of Singly & Doubly Linked Lists (Topic 3.1) and Linked List Problems (Topic 3.2) from Module 3.
Linked List Structures (3.1)

Singly linked, doubly linked, circular lists, node creation and traversal

Linked List Problems (3.2)

Cycle detection, reversal, merging, middle node, and pointer techniques

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

Topics Covered

3.1 Singly & Doubly Linked Lists

  • Linked list structure and node creation - Node class design, head/tail pointers
  • Insertion, deletion, and traversal - Add/remove at any position, iterate
  • Doubly linked lists and circular lists - Prev pointers, circular connections
  • Fast and slow pointer technique - Two-pointer pattern for lists

3.2 Linked List Problems

  • Detecting cycles and finding middle node - Floyd's cycle detection
  • Reversing linked lists - Iterative and recursive approaches
  • Merging sorted lists - Two-pointer merge technique
  • Complex linked list manipulation - Intersection, partitioning
03

Part 1: Linked List Implementation (75 Points)

Implement complete linked list data structures with all essential operations. Each implementation must include proper error handling and edge cases.

P1
Singly Linked List (25 points)

Create a class SinglyLinkedList.java with a nested Node class:

public class SinglyLinkedList<T> {
    private class Node {
        T data;
        Node next;
        Node(T data) { this.data = data; }
    }
    
    private Node head;
    private Node tail;
    private int size;
    
    // Required methods (implement all):
    public void addFirst(T data);      // O(1)
    public void addLast(T data);       // O(1) with tail pointer
    public void addAt(int index, T data); // O(n)
    
    public T removeFirst();            // O(1)
    public T removeLast();             // O(n) - must traverse
    public T removeAt(int index);      // O(n)
    public boolean remove(T data);     // Remove first occurrence
    
    public T getFirst();               // O(1)
    public T getLast();                // O(1) with tail pointer
    public T get(int index);           // O(n)
    public int indexOf(T data);        // O(n)
    public boolean contains(T data);   // O(n)
    
    public int size();
    public boolean isEmpty();
    public void clear();
    public void printList();           // Print all elements
}

Requirements:

  • Use generics (<T>) for type safety
  • Maintain both head and tail pointers
  • Track size for O(1) size() operation
  • Throw appropriate exceptions for invalid operations
P2
Doubly Linked List (25 points)

Create a class DoublyLinkedList.java with bidirectional navigation:

public class DoublyLinkedList<T> {
    private class Node {
        T data;
        Node prev;
        Node next;
        Node(T data) { this.data = data; }
    }
    
    private Node head;
    private Node tail;
    private int size;
    
    // All methods from SinglyLinkedList, PLUS:
    public T removeLast();             // O(1) - with prev pointer!
    public void reverse();             // O(n) - in-place reversal
    public void printReverse();        // Print from tail to head
    
    // Iterator-like methods:
    public Node getHead();             // For external traversal
    public Node getTail();
}

Key Improvement: removeLast() should be O(1) using the prev pointer!

P3
Circular Linked List (25 points)

Create a class CircularLinkedList.java where the last node points back to head:

public class CircularLinkedList<T> {
    private class Node {
        T data;
        Node next;
        Node(T data) { this.data = data; }
    }
    
    private Node head;
    private Node tail;  // tail.next always points to head
    private int size;
    
    // Core operations:
    public void add(T data);           // Add at end
    public void addFirst(T data);      // Add at beginning
    public T remove(T data);           // Remove first occurrence
    public T removeFirst();
    
    // Circular-specific operations:
    public void rotate(int k);         // Rotate list by k positions
    public boolean isCircular();       // Verify circular property
    public void traverse(int times);   // Print list 'times' rotations
    
    // Josephus Problem:
    public T josephus(int k);          // Return survivor (every k-th eliminated)
}
// Josephus Problem Example:
// People in circle: [1, 2, 3, 4, 5], eliminate every 2nd person
// Elimination order: 2, 4, 1, 5
// Survivor: 3
CircularLinkedList<Integer> circle = new CircularLinkedList<>();
for (int i = 1; i <= 5; i++) circle.add(i);
circle.josephus(2);  // Returns: 3
04

Part 2: Linked List Problems (75 Points)

Solve these classic linked list problems. Create a class LinkedListProblems.java containing all solutions.

P4
Cycle Detection & Analysis (15 points)

Implement cycle detection using Floyd's algorithm:

public class LinkedListProblems {
    
    // P4a: Detect if a cycle exists
    public boolean hasCycle(ListNode head);
    
    // P4b: Find the node where cycle begins (return null if no cycle)
    public ListNode detectCycleStart(ListNode head);
    
    // P4c: Find the length of the cycle (return 0 if no cycle)
    public int cycleLength(ListNode head);
}

// Example:
// 1 -> 2 -> 3 -> 4 -> 5
//           ^         |
//           |_________|
// hasCycle() returns true
// detectCycleStart() returns node with value 3
// cycleLength() returns 3
P5
Reversal Operations (15 points)

Implement various reversal techniques:

// P5a: Reverse entire list iteratively
public ListNode reverseIterative(ListNode head);

// P5b: Reverse entire list recursively
public ListNode reverseRecursive(ListNode head);

// P5c: Reverse nodes in groups of k
// [1,2,3,4,5], k=2 → [2,1,4,3,5]
// [1,2,3,4,5], k=3 → [3,2,1,4,5]
public ListNode reverseInGroups(ListNode head, int k);

// P5d: Reverse between positions left and right (1-indexed)
// [1,2,3,4,5], left=2, right=4 → [1,4,3,2,5]
public ListNode reverseBetween(ListNode head, int left, int right);
P6
Fast & Slow Pointer Problems (15 points)

Use the two-pointer technique:

// P6a: Find the middle node (if even length, return second middle)
// [1,2,3,4,5] → 3
// [1,2,3,4] → 3
public ListNode findMiddle(ListNode head);

// P6b: Check if list is palindrome
// [1,2,3,2,1] → true
// [1,2,3,4] → false
public boolean isPalindrome(ListNode head);

// P6c: Find nth node from end
// [1,2,3,4,5], n=2 → 4
public ListNode nthFromEnd(ListNode head, int n);

// P6d: Remove nth node from end and return head
// [1,2,3,4,5], n=2 → [1,2,3,5]
public ListNode removeNthFromEnd(ListNode head, int n);
P7
Merge & Sort Operations (15 points)

Implement merging and sorting for linked lists:

// P7a: Merge two sorted lists into one sorted list
// [1,3,5] + [2,4,6] → [1,2,3,4,5,6]
public ListNode mergeTwoSorted(ListNode l1, ListNode l2);

// P7b: Merge k sorted lists
// [[1,4,5], [1,3,4], [2,6]] → [1,1,2,3,4,4,5,6]
public ListNode mergeKSorted(ListNode[] lists);

// P7c: Sort a linked list using merge sort - O(n log n)
public ListNode sortList(ListNode head);

// P7d: Partition list around value x
// All nodes less than x come before nodes >= x
// [1,4,3,2,5,2], x=3 → [1,2,2,4,3,5]
public ListNode partition(ListNode head, int x);
P8
Advanced Linked List Problems (15 points)

Solve these challenging problems:

// P8a: Find intersection point of two lists
// List1: 1 -> 2 -> 3
//                   \
//                    -> 6 -> 7 -> null
//                   /
// List2:      4 -> 5
// Returns: node with value 6
public ListNode getIntersection(ListNode headA, ListNode headB);

// P8b: Add two numbers represented as linked lists (digits reversed)
// [2,4,3] + [5,6,4] = 342 + 465 = 807 → [7,0,8]
public ListNode addTwoNumbers(ListNode l1, ListNode l2);

// P8c: Flatten a multilevel doubly linked list
// 1 - 2 - 3 - 4 - 5
//     |
//     6 - 7
//     |
//     8
// Flattens to: 1 - 2 - 6 - 8 - 7 - 3 - 4 - 5
public DoublyListNode flatten(DoublyListNode head);

// P8d: Copy list with random pointer
// Each node has a random pointer to any node or null
public RandomListNode copyRandomList(RandomListNode head);
05

Submission

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

Required Repository Name
java-linked-lists-dsa
github.com/<your-username>/java-linked-lists-dsa
Required Files
java-linked-lists-dsa/
├── src/
│   ├── lists/
│   │   ├── SinglyLinkedList.java      # P1
│   │   ├── DoublyLinkedList.java      # P2
│   │   └── CircularLinkedList.java    # P3
│   ├── problems/
│   │   ├── LinkedListProblems.java    # P4-P8
│   │   ├── ListNode.java              # Singly linked node
│   │   ├── DoublyListNode.java        # Doubly linked node
│   │   └── RandomListNode.java        # Node with random pointer
│   └── Main.java                      # Demo all solutions
├── test/
│   └── LinkedListTests.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 your approach for cycle detection and reversal
  • Instructions to compile and run the code
Do Include
  • All 3 linked list implementations (P1-P3)
  • All problem solutions (P4-P8)
  • Main.java with comprehensive tests
  • Time/space complexity in code comments
  • Edge case handling (empty list, single node)
  • Generics in list implementations
Do Not Include
  • Java's built-in LinkedList class
  • 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 linked list implementations thoroughly with edge cases: empty lists, single node, operations at head/tail, and invalid indices. 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: Singly Linked List 25 All operations work, generics, proper head/tail handling
P2: Doubly Linked List 25 O(1) removeLast, proper prev pointer maintenance
P3: Circular Linked List 25 Circular property maintained, Josephus problem works
P4: Cycle Detection 15 Floyd's algorithm, finds cycle start and length
P5: Reversal Operations 15 Iterative & recursive work, in-groups and between positions
P6: Fast & Slow Pointer 15 Correct middle finding, palindrome check, nth from end
P7: Merge & Sort 15 O(n log n) sort, merge works for k lists
P8: Advanced Problems 15 Intersection, add numbers, flatten, random copy
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

Data Structure Design

Building linked list classes from scratch with proper encapsulation and generics

Pointer Manipulation

Understanding how to modify next/prev pointers for insertion, deletion, and reversal

Cycle Detection

Floyd's tortoise and hare algorithm for detecting and analyzing cycles

Two-Pointer Technique

Using fast and slow pointers for middle finding, palindrome check, and more

08

Pro Tips

Implementation Tips
  • Always handle edge cases: null head, single node
  • Use dummy nodes to simplify insertion/deletion at head
  • Draw diagrams to visualize pointer changes
  • Update size counter in every add/remove operation
Cycle Detection Tips
  • Fast pointer moves 2 steps, slow moves 1 step
  • If they meet, cycle exists
  • To find start: reset one pointer to head, move both by 1
  • Cycle length: count steps from meeting point back to itself
Reversal Tips
  • Use three pointers: prev, current, next
  • Save next before changing current.next
  • For recursive: reverse rest, then fix current
  • In-groups: count k nodes, reverse, connect
Common Pitfalls
  • Forgetting to update tail pointer after operations
  • Losing reference to next node during reversal
  • Off-by-one errors in nth from end
  • Not handling circular list termination
09

Pre-Submission Checklist

Part 1: Implementations
Part 2: Problems
Repository Checklist