PYnative

Python Programming

  • Learn Python ▼
    • Python Tutorials
    • Python Basics
    • Python Interview Q&As
  • Exercises ▼
    • Python Exercises
    • C++ Exercises
    • C Programming Exercises
    • Java Exercises
    • C# Exercises
  • Quizzes
  • Online Compilers▼
    • Online Python Code Editor
    • Online C Compiler
    • Online C++ Compiler
    • Online Java Compiler
    • Online C# Compiler
Home » Java Exercises » Java LinkedList Exercises: 25 Coding Problems with Solutions

Java LinkedList Exercises: 25 Coding Problems with Solutions

Updated on: July 6, 2026 | Leave a Comment

This collection of 25 Java exercises covers both Java’s built-in java.util.LinkedList and hand-built Node-based linked lists, so you understand the structure from both sides.

  • The first half works entirely with java.util.LinkedList: appending, inserting, and iterating from a position, the Deque-style methods, reverse iteration, shuffling, cloning, and converting to and from arrays.
  • The second half switches to a custom singly linked list built from raw Node objects, covering iterative and recursive reversal, the fast-and-slow pointer technique for finding the middle element, Floyd’s cycle detection, in-place duplicate removal, and merging two sorted lists.

Each exercise includes a Problem Statement, Purpose, Hint, and a Solution with Explanation, so the pointer manipulation behind each operation is just as clear as the final result.

  • Also, See: Java Exercises with over 20+ topic-wise sets and 575+ coding questions to practice.
  • Practice questions using our Online Java Compiler
+ Table of Contents (25 Exercises)

Table of contents

  • Exercise 1: Append Element
  • Exercise 2: Iterate from Position
  • Exercise 3: Reverse Iteration
  • Exercise 4: Insert at Specific Position
  • Exercise 5: Insert First & Last
  • Exercise 6: Prepend Element
  • Exercise 7: Bulk Insertion
  • Exercise 8: Find Occurrences
  • Exercise 9: Display Positions
  • Exercise 10: Remove Element
  • Exercise 11: Remove Extremes
  • Exercise 12: Clear List
  • Exercise 13: Swap Elements
  • Exercise 14: Shuffle List
  • Exercise 15: Join Lists
  • Exercise 16: Clone List
  • Exercise 17: Pop Element
  • Exercise 18: Peek Element
  • Exercise 19: Check Existence
  • Exercise 20: Convert to Array
  • Exercise 21: Reverse a LinkedList
  • Exercise 22: Find Middle Element
  • Exercise 23: Cycle Detection
  • Exercise 24: Remove Duplicates
  • Exercise 25: Merge Two Sorted Lists

Exercise 1: Append Element

Problem Statement: Write a Java program to append a specified element to the end of a LinkedList.

Purpose: This exercise helps you practice the most basic write operation on a LinkedList, adding a new node to its tail, which is a constant time operation thanks to the list’s internal tail reference.

Given Input: LinkedList<String> fruits = new LinkedList<>(Arrays.asList("Apple", "Banana", "Mango"));

Expected Output: [Apple, Banana, Mango, Orange]

▼ Hint

Call the add(element) method, which appends the given element to the end of the list by default.

▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> fruits = new LinkedList<>(Arrays.asList("Apple", "Banana", "Mango"));

        fruits.add("Orange");

        System.out.println(fruits);
    }
}Code language: Java (java)

Explanation:

  • new LinkedList<>(Arrays.asList(...)): Creates a LinkedList pre-populated with the given elements, using Arrays.asList() to build the initial list.
  • fruits.add("Orange"): Appends "Orange" as a new node linked after the current last element, since add() with a single argument always inserts at the tail.

Exercise 2: Iterate from Position

Problem Statement: Write a program to iterate through all elements in a LinkedList starting at a specified position.

Purpose: This exercise introduces ListIterator, which allows you to begin traversal at any index rather than always starting from the first element, a capability a simple for loop does not offer directly on a linked structure.

Given Input: LinkedList<String> colors = new LinkedList<>(Arrays.asList("Red", "Green", "Blue", "Yellow", "Purple")); int startPosition = 2;

Blue
Yellow
Purple
▼ Hint
  • Get a ListIterator using colors.listIterator(startPosition), which starts the cursor right before the element at that index.
  • Use a while (iterator.hasNext()) loop to move forward from that point.
  • Call iterator.next() inside the loop to retrieve and advance past each element.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;
import java.util.ListIterator;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> colors = new LinkedList<>(Arrays.asList("Red", "Green", "Blue", "Yellow", "Purple"));
        int startPosition = 2;

        ListIterator<String> iterator = colors.listIterator(startPosition);
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}Code language: Java (java)

Explanation:

  • colors.listIterator(startPosition): Returns a ListIterator positioned just before the element at index 2, skipping the earlier elements entirely.
  • iterator.hasNext(): Checks whether there is another element ahead of the cursor before attempting to read it.
  • iterator.next(): Returns the next element in the list and moves the cursor one step forward, which is how each iteration prints a new value.

Exercise 3: Reverse Iteration

Problem Statement: Write a program to iterate a LinkedList in reverse order.

Purpose: This exercise shows how LinkedList supports efficient backward traversal through its built-in descendingIterator(), without needing to manually reverse the list or use index-based access.

Given Input: LinkedList<Integer> numbers = new LinkedList<>(Arrays.asList(10, 20, 30, 40));

40
30
20
10
▼ Hint
  • Call numbers.descendingIterator() to get an Iterator that walks the list from the last element to the first.
  • Use a while (iterator.hasNext()) loop exactly as you would with a normal iterator.
  • Each call to next() returns the elements in reverse order automatically.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<Integer> numbers = new LinkedList<>(Arrays.asList(10, 20, 30, 40));

        Iterator<Integer> iterator = numbers.descendingIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}Code language: Java (java)

Explanation:

  • numbers.descendingIterator(): Returns an iterator that starts at the tail node and moves backward toward the head, unlike the default iterator which moves forward.
  • iterator.hasNext(): Still means “is there another element to visit,” even though this particular iterator is moving in the reverse direction.
  • iterator.next(): Returns the previous element in list order each time it is called, producing the reversed sequence in the output.

Exercise 4: Insert at Specific Position

Problem Statement: Insert a specified element at a given position in a LinkedList.

Purpose: This exercise practices inserting into the middle of a list at an arbitrary index, a task that is efficient for a LinkedList since it only requires relinking neighboring nodes rather than shifting elements.

Given Input: LinkedList<String> cities = new LinkedList<>(Arrays.asList("Delhi", "Mumbai", "Chennai")); int position = 1; String newCity = "Pune";

Expected Output: [Delhi, Pune, Mumbai, Chennai]

▼ Hint

Use the two-argument version of add(), cities.add(position, newCity), which shifts the element currently at that index and everything after it one step to the right.

▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> cities = new LinkedList<>(Arrays.asList("Delhi", "Mumbai", "Chennai"));
        int position = 1;
        String newCity = "Pune";

        cities.add(position, newCity);

        System.out.println(cities);
    }
}Code language: Java (java)

Explanation:

  • cities.add(position, newCity): Inserts "Pune" at index 1, pushing "Mumbai" and "Chennai" each one position further along.
  • Underlying behavior: Because LinkedList stores elements as linked nodes, this insertion only involves updating a few node references internally rather than physically moving every subsequent element.

Exercise 5: Insert First & Last

Problem Statement: Insert elements at the first and last positions of a LinkedList using addFirst() and addLast().

Purpose: This exercise introduces the Deque style methods available on LinkedList, which give explicit, readable control over inserting at either end of the list.

Given Input: LinkedList<String> queue = new LinkedList<>(Arrays.asList("B", "C", "D"));

Expected Output: [A, B, C, D, E]

▼ Hint
  • Call queue.addFirst("A") to place "A" before the current first element.
  • Call queue.addLast("E") to place "E" after the current last element.
  • The order in which you call these two methods does not affect the final result, since they operate on opposite ends of the list.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> queue = new LinkedList<>(Arrays.asList("B", "C", "D"));

        queue.addFirst("A");
        queue.addLast("E");

        System.out.println(queue);
    }
}Code language: Java (java)

Explanation:

  • queue.addFirst("A"): Inserts "A" as the new head node, making it the first element the list returns during iteration.
  • queue.addLast("E"): Inserts "E" as the new tail node, appending it after every existing element.
  • Result: Both operations run in constant time regardless of the list’s size, since LinkedList keeps direct references to both its head and tail nodes.

Exercise 6: Prepend Element

Problem Statement: Insert a specified element at the front of a LinkedList.

Purpose: This exercise reinforces front-of-list insertion specifically, comparing the dedicated addFirst() method against the equivalent two-argument add(0, element) call.

Given Input: LinkedList<Integer> scores = new LinkedList<>(Arrays.asList(75, 82, 90));

Expected Output: [60, 75, 82, 90]

▼ Hint

Call scores.addFirst(60), which places the new value directly before the current head node, shifting everything else back by one position without changing their relative order.

▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<Integer> scores = new LinkedList<>(Arrays.asList(75, 82, 90));

        scores.addFirst(60);

        System.out.println(scores);
    }
}Code language: Java (java)

Explanation:

  • scores.addFirst(60): Places 60 as the new head of the list, before the value that used to be first.
  • Equivalent call: scores.add(0, 60) would produce the exact same result, since inserting at index 0 is precisely what addFirst() does under the hood.

Exercise 7: Bulk Insertion

Problem Statement: Insert a collection of elements at a specified position into an existing LinkedList.

Purpose: This exercise practices merging an entire collection into a list at a chosen index in a single call, rather than inserting each element one at a time in a loop.

Given Input: LinkedList<String> days = new LinkedList<>(Arrays.asList("Monday", "Friday")); List<String> midweek = Arrays.asList("Tuesday", "Wednesday", "Thursday"); int position = 1;

Expected Output: [Monday, Tuesday, Wednesday, Thursday, Friday]

▼ Hint

Use days.addAll(position, midweek), which inserts every element of midweek starting at index 1, preserving their original order relative to each other.

▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> days = new LinkedList<>(Arrays.asList("Monday", "Friday"));
        List<String> midweek = Arrays.asList("Tuesday", "Wednesday", "Thursday");
        int position = 1;

        days.addAll(position, midweek);

        System.out.println(days);
    }
}Code language: Java (java)

Explanation:

  • days.addAll(position, midweek): Inserts the entire midweek collection starting at index 1, shifting "Friday" further down the list.
  • Order preserved: The elements of midweek appear in the result in the same sequence they had in the source collection.

Exercise 8: Find Occurrences

Problem Statement: Get the first and last occurrence of a specified element in a LinkedList.

Purpose: This exercise practices locating the position of duplicate values within a list using built-in search methods, instead of writing a manual loop with index tracking.

Given Input: LinkedList<String> letters = new LinkedList<>(Arrays.asList("A", "B", "C", "B", "D", "B")); String target = "B";

First occurrence: 1
Last occurrence: 5
▼ Hint
  • Call letters.indexOf(target) to find the index of the first matching element.
  • Call letters.lastIndexOf(target) to find the index of the last matching element.
  • Both methods return -1 if the element does not appear anywhere in the list.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> letters = new LinkedList<>(Arrays.asList("A", "B", "C", "B", "D", "B"));
        String target = "B";

        int firstIndex = letters.indexOf(target);
        int lastIndex = letters.lastIndexOf(target);

        System.out.println("First occurrence: " + firstIndex);
        System.out.println("Last occurrence: " + lastIndex);
    }
}Code language: Java (java)

Explanation:

  • letters.indexOf(target): Scans the list from the beginning and returns the index of the first element equal to "B".
  • letters.lastIndexOf(target): Scans the list from the end and returns the index of the last element equal to "B".
  • Equality check: Both methods rely on the equals() method of the elements to decide what counts as a match.

Exercise 9: Display Positions

Problem Statement: Display all elements of a LinkedList along with their corresponding index positions.

Purpose: This exercise practices pairing each element with its index while iterating, a common formatting need when displaying list contents in a readable, numbered way.

Given Input: LinkedList<String> movies = new LinkedList<>(Arrays.asList("Inception", "Interstellar", "Tenet"));

Index 0: Inception
Index 1: Interstellar
Index 2: Tenet
▼ Hint
  • Use a regular indexed for loop from 0 to movies.size() - 1.
  • Inside the loop, call movies.get(i) to retrieve the element at each index.
  • Print the index and the element together on each line.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> movies = new LinkedList<>(Arrays.asList("Inception", "Interstellar", "Tenet"));

        for (int i = 0; i < movies.size(); i++) {
            System.out.println("Index " + i + ": " + movies.get(i));
        }
    }
}Code language: Java (java)

Explanation:

  • for (int i = 0; i < movies.size(); i++): Walks through every valid index in the list, from the first position to the last.
  • movies.get(i): Retrieves the element at index i. Note that repeated calls like this are less efficient on a LinkedList than on an ArrayList, since each call must traverse the list from the nearer end.
  • Output format: Combining i and the retrieved element in one print statement produces a clearly numbered listing.

Exercise 10: Remove Element

Problem Statement: Remove a specific element from a LinkedList.

Purpose: This exercise practices removing by value rather than by index, and highlights the overload ambiguity that can arise between remove(Object) and remove(int) when working with a list of integers.

Given Input: LinkedList<String> playlist = new LinkedList<>(Arrays.asList("Song A", "Song B", "Song C")); String toRemove = "Song B";

Expected Output: [Song A, Song C]

▼ Hint
  • Call playlist.remove(toRemove), which searches for the first element equal to toRemove and removes it.
  • This method returns a boolean indicating whether an element was actually found and removed.
  • For a LinkedList<Integer>, remember that remove(5) would remove the element at index 5, while remove(Integer.valueOf(5)) is needed to remove the value 5 itself.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> playlist = new LinkedList<>(Arrays.asList("Song A", "Song B", "Song C"));
        String toRemove = "Song B";

        playlist.remove(toRemove);

        System.out.println(playlist);
    }
}Code language: Java (java)

Explanation:

  • playlist.remove(toRemove): Since toRemove is a String, this calls the remove(Object) overload, which removes the first element that matches by equals().
  • Node relinking: Internally, the list removes the matching node by reconnecting the nodes on either side of it directly to each other.
  • Overload caution: With a LinkedList<Integer>, passing a plain int to remove() is treated as an index, not a value, which is a common source of bugs worth calling out separately from this string example.

Exercise 11: Remove Extremes

Problem Statement: Remove the first and last elements from a LinkedList.

Purpose: This exercise practices removing from both ends of a list using dedicated methods, reinforcing why LinkedList is well suited for operations at the head and tail.

Given Input: LinkedList<Integer> numbers = new LinkedList<>(Arrays.asList(5, 10, 15, 20, 25));

Expected Output: [10, 15, 20]

▼ Hint
  • Call numbers.removeFirst() to remove the head element.
  • Call numbers.removeLast() to remove the tail element.
  • Both methods throw NoSuchElementException if the list is empty, so they should only be called when you know at least one element exists.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<Integer> numbers = new LinkedList<>(Arrays.asList(5, 10, 15, 20, 25));

        numbers.removeFirst();
        numbers.removeLast();

        System.out.println(numbers);
    }
}Code language: Java (java)

Explanation:

  • numbers.removeFirst(): Removes 5, relinking the list so the second element becomes the new head.
  • numbers.removeLast(): Removes 25, relinking the list so the second to last element becomes the new tail.
  • Result: Both operations run in constant time, since LinkedList keeps direct references to its head and tail nodes.

Exercise 12: Clear List

Problem Statement: Remove all elements from a LinkedList and verify that it is empty.

Purpose: This exercise practices resetting a list back to an empty state and checking that state afterward, a common pattern when reusing a collection across multiple operations.

Given Input: LinkedList<String> tasks = new LinkedList<>(Arrays.asList("Task1", "Task2", "Task3"));

Expected Output: Is empty: true

▼ Hint
  • Call tasks.clear() to remove every element from the list at once.
  • Call tasks.isEmpty() afterward, which returns true only when the list has zero elements.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> tasks = new LinkedList<>(Arrays.asList("Task1", "Task2", "Task3"));

        tasks.clear();

        System.out.println("Is empty: " + tasks.isEmpty());
    }
}Code language: Java (java)

Explanation:

  • tasks.clear(): Removes every node from the list, resetting its size to zero without creating a new list object.
  • tasks.isEmpty(): Returns true since size() is now 0, confirming the list was successfully cleared.

Exercise 13: Swap Elements

Problem Statement: Swap two specified elements in a LinkedList.

Purpose: This exercise practices exchanging the values at two positions in a list, using the utility method built for this exact purpose instead of manually juggling temporary variables.

Given Input: LinkedList<String> team = new LinkedList<>(Arrays.asList("Raj", "Simran", "Aman", "Divya")); int pos1 = 0; int pos2 = 3;

Expected Output: [Divya, Simran, Aman, Raj]

▼ Hint

Use Collections.swap(team, pos1, pos2) from java.util.Collections, which exchanges the elements found at the two given indices.

▼ Solution & Explanation
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> team = new LinkedList<>(Arrays.asList("Raj", "Simran", "Aman", "Divya"));
        int pos1 = 0;
        int pos2 = 3;

        Collections.swap(team, pos1, pos2);

        System.out.println(team);
    }
}Code language: Java (java)

Explanation:

  • Collections.swap(team, pos1, pos2): Reads the elements currently at index 0 and index 3, then writes each one back into the other’s position.
  • Result: "Raj" and "Divya" exchange places while "Simran" and "Aman" stay exactly where they were.

Exercise 14: Shuffle List

Problem Statement: Shuffle the elements of a LinkedList randomly.

Purpose: This exercise practices randomizing the order of a list’s elements in place using a built-in utility, useful for tasks like shuffling a deck of cards or randomizing quiz questions.

Given Input: LinkedList<Integer> deck = new LinkedList<>(Arrays.asList(1, 2, 3, 4, 5));

Expected Output: A randomly reordered list, for example [3, 1, 5, 2, 4]

▼ Hint
  • Call Collections.shuffle(deck) from java.util.Collections.
  • This method rearranges the elements in place using a uniformly random permutation, so the output will differ between runs.
  • Passing a fixed Random seed to an overloaded version of shuffle() makes the result reproducible for testing.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<Integer> deck = new LinkedList<>(Arrays.asList(1, 2, 3, 4, 5));

        Collections.shuffle(deck);

        System.out.println(deck);
    }
}Code language: Java (java)

Explanation:

  • Collections.shuffle(deck): Randomly reorders the elements of deck in place, using an internally managed source of randomness.
  • Non-deterministic output: Running the program multiple times will typically produce a different order each time, since no fixed seed was provided.

Exercise 15: Join Lists

Problem Statement: Concatenate two different LinkedLists into a single list.

Purpose: This exercise practices merging the contents of one list into another, appending all elements of the second list after the elements of the first.

Given Input: LinkedList<String> listA = new LinkedList<>(Arrays.asList("A", "B")); LinkedList<String> listB = new LinkedList<>(Arrays.asList("C", "D"));

Expected Output: [A, B, C, D]

▼ Hint

Call listA.addAll(listB), which appends every element of listB to the end of listA in order, leaving listB itself unchanged.

▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> listA = new LinkedList<>(Arrays.asList("A", "B"));
        LinkedList<String> listB = new LinkedList<>(Arrays.asList("C", "D"));

        listA.addAll(listB);

        System.out.println(listA);
    }
}Code language: Java (java)

Explanation:

  • listA.addAll(listB): Appends every element of listB onto the end of listA, extending its size by the number of elements added.
  • listB untouched: The elements are copied by reference into listA, but listB itself remains [C, D] afterward.

Exercise 16: Clone List

Problem Statement: Clone an existing LinkedList to another LinkedList (shallow copy).

Purpose: This exercise practices creating an independent copy of a list’s structure, while understanding that a shallow copy still shares the same element objects as the original.

Given Input: LinkedList<String> original = new LinkedList<>(Arrays.asList("X", "Y", "Z"));

Original: [X, Y, Z]
Cloned: [X, Y, Z]
▼ Hint
  • Call original.clone(), which returns an Object that must be cast back to LinkedList<String>.
  • The clone contains a new list structure, but the elements themselves are the same object references as in the original, which is what makes it a shallow copy.
  • Modifying the cloned list’s structure, such as adding or removing elements, will not affect the original list.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> original = new LinkedList<>(Arrays.asList("X", "Y", "Z"));

        @SuppressWarnings("unchecked")
        LinkedList<String> cloned = (LinkedList<String>) original.clone();

        System.out.println("Original: " + original);
        System.out.println("Cloned: " + cloned);
    }
}Code language: Java (java)

Explanation:

  • original.clone(): Returns a new LinkedList object containing the same elements as original, but as a raw Object that needs an explicit cast.
  • Shallow copy: The new list has its own set of nodes, but each node stores a reference to the exact same String objects held by original, rather than deep copies of them.
  • @SuppressWarnings("unchecked"): Added because casting the result of clone() to a generic type produces an unchecked cast warning from the compiler.

Exercise 17: Pop Element

Problem Statement: Remove and return the first element of a LinkedList, treating it like a stack or queue.

Purpose: This exercise introduces the Deque style pop() method, showing how LinkedList can act directly as a stack without needing a separate Stack class.

Given Input: LinkedList<String> history = new LinkedList<>(Arrays.asList("PageA", "PageB", "PageC"));

Popped: PageA
Remaining: [PageB, PageC]
▼ Hint
  • Call history.pop(), which removes and returns the head element in a single call.
  • This behaves identically to removeFirst(), but the name pop() matches the vocabulary used when treating the list as a stack.
  • Save the return value in a variable before printing it, since the element is removed from the list as soon as pop() runs.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> history = new LinkedList<>(Arrays.asList("PageA", "PageB", "PageC"));

        String popped = history.pop();

        System.out.println("Popped: " + popped);
        System.out.println("Remaining: " + history);
    }
}Code language: Java (java)

Explanation:

  • history.pop(): Removes "PageA" from the head of the list and returns it in the same call, matching typical stack terminology.
  • String popped = history.pop();: Captures the removed value so it can still be used after it has left the list.
  • Remaining list: After the call, history contains only [PageB, PageC], confirming the head element was removed.

Exercise 18: Peek Element

Problem Statement: Retrieve, but do not remove, the first and last elements of a LinkedList.

Purpose: This exercise practices reading from both ends of a list without modifying it, which is useful when you need to check upcoming values before deciding whether to remove them.

Given Input: LinkedList<Integer> queue = new LinkedList<>(Arrays.asList(100, 200, 300));

First: 100
Last: 300
▼ Hint
  • Call queue.peekFirst() to view the head element without removing it.
  • Call queue.peekLast() to view the tail element without removing it.
  • Both methods return null instead of throwing an exception if the list is empty, which makes them safer than getFirst() and getLast() in that scenario.
▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<Integer> queue = new LinkedList<>(Arrays.asList(100, 200, 300));

        System.out.println("First: " + queue.peekFirst());
        System.out.println("Last: " + queue.peekLast());
    }
}Code language: Java (java)

Explanation:

  • queue.peekFirst(): Reads the value at the head of the list without detaching its node, leaving the list’s size unchanged.
  • queue.peekLast(): Reads the value at the tail of the list in the same non-destructive way.
  • List unchanged: Unlike pop() or removeFirst(), neither peek call removes anything, so queue still holds all three original elements afterward.

Exercise 19: Check Existence

Problem Statement: Check if a particular element exists in a LinkedList.

Purpose: This exercise practices membership testing, confirming whether a value is present anywhere in the list before deciding on further action such as insertion or removal.

Given Input: LinkedList<String> guestList = new LinkedList<>(Arrays.asList("Alice", "Bob", "Carol")); String name = "Bob";

Expected Output: Bob is on the guest list: true

▼ Hint

Call guestList.contains(name), which scans the list and returns true as soon as it finds an element equal to name.

▼ Solution & Explanation
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> guestList = new LinkedList<>(Arrays.asList("Alice", "Bob", "Carol"));
        String name = "Bob";

        boolean exists = guestList.contains(name);

        System.out.println(name + " is on the guest list: " + exists);
    }
}Code language: Java (java)

Explanation:

  • guestList.contains(name): Walks through the list comparing each element to name using equals(), stopping early as soon as a match is found.
  • boolean exists: Stores the result so it can be reused or printed, rather than checking membership more than once.

Exercise 20: Convert to Array

Problem Statement: Convert a LinkedList into a standard Java Array or an ArrayList.

Purpose: This exercise practices converting between collection types, showing how a LinkedList‘s contents can be exported into either a fixed size array or a different List implementation.

Given Input: LinkedList<String> source = new LinkedList<>(Arrays.asList("One", "Two", "Three"));

Array: [One, Two, Three]
ArrayList: [One, Two, Three]
▼ Hint
  • Call source.toArray(new String[0]) to get a typed String[] array containing all the elements.
  • Pass source directly into the ArrayList constructor, new ArrayList<>(source), to build an independent ArrayList with the same elements.
  • Use Arrays.toString() to print the array in a readable format, since arrays do not override toString() by default.
▼ Solution & Explanation
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> source = new LinkedList<>(Arrays.asList("One", "Two", "Three"));

        String[] array = source.toArray(new String[0]);
        ArrayList<String> arrayList = new ArrayList<>(source);

        System.out.println("Array: " + Arrays.toString(array));
        System.out.println("ArrayList: " + arrayList);
    }
}Code language: Java (java)

Explanation:

  • source.toArray(new String[0]): Copies every element of the LinkedList into a new String[] array, using the supplied empty array only to indicate the array’s type.
  • new ArrayList<>(source): Builds a brand new ArrayList initialized with all the elements currently in source.
  • Arrays.toString(array): Converts the array into a readable String for printing, since printing an array directly would show its memory reference instead of its contents.

Exercise 21: Reverse a LinkedList

Problem Statement: Implement a method to reverse a custom singly LinkedList both iteratively and recursively.

Purpose: This exercise moves away from the built-in java.util.LinkedList and works with raw Node objects directly, building the core pointer manipulation skills needed for linked list interview questions and custom data structure design.

Given Input: Original list: 1 -> 2 -> 3 -> 4 -> 5

Original list: 1 -> 2 -> 3 -> 4 -> 5
Reversed (iterative): 5 -> 4 -> 3 -> 2 -> 1
Reversed (recursive): 5 -> 4 -> 3 -> 2 -> 1
▼ Hint
  • For the iterative version, keep three references: prev, current, and a temporary next node.
  • In each step, save current.next, then point current.next back to prev, then move prev and current one step forward.
  • For the recursive version, recurse to the end of the list first, then, while unwinding, make each node’s next node point back to it.
  • The base case for the recursive version is a null node or a node with no next, which becomes the new head.
▼ Solution & Explanation
class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
    }
}

class SinglyLinkedList {
    Node head;

    void add(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            return;
        }
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
    }

    void reverseIterative() {
        Node prev = null;
        Node current = head;
        while (current != null) {
            Node nextNode = current.next;
            current.next = prev;
            prev = current;
            current = nextNode;
        }
        head = prev;
    }

    Node reverseRecursive(Node node) {
        if (node == null || node.next == null) {
            return node;
        }
        Node newHead = reverseRecursive(node.next);
        node.next.next = node;
        node.next = null;
        return newHead;
    }

    void printList() {
        Node temp = head;
        StringBuilder sb = new StringBuilder();
        while (temp != null) {
            sb.append(temp.data);
            if (temp.next != null) {
                sb.append(" -> ");
            }
            temp = temp.next;
        }
        System.out.println(sb);
    }
}

public class Main {
    public static void main(String[] args) {
        SinglyLinkedList list = new SinglyLinkedList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

        System.out.print("Original list: ");
        list.printList();

        list.reverseIterative();
        System.out.print("Reversed (iterative): ");
        list.printList();

        list.head = list.reverseRecursive(list.head);
        System.out.print("Reversed (recursive): ");
        list.printList();
    }
}Code language: Java (java)

Explanation:

  • Node nextNode = current.next;: Saves a reference to the rest of the list before it gets overwritten, so the traversal is not lost when the pointer is redirected.
  • current.next = prev;: Flips the direction of the current node’s pointer to face backward instead of forward.
  • head = prev;: After the loop ends, current is null and prev is sitting on the last node visited, which is now the new head of the reversed list.
  • node.next.next = node;: In the recursive version, once the rest of the list has already been reversed, this line makes the following node point back at the current one.
  • node.next = null;: Breaks the current node’s old forward link so it does not create a cycle with the node that now points back to it.

Exercise 22: Find Middle Element

Problem Statement: Find the exact middle node of a LinkedList in a single pass using the two-pointer technique (fast and slow pointers).

Purpose: This exercise introduces the fast and slow pointer pattern, a technique that finds the midpoint of a list without first counting its length, since a singly linked list has no direct index access.

Given Input: List: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7

Expected Output: Middle element: 4

▼ Hint
  • Start two references, slow and fast, both pointing at the head.
  • In each loop iteration, move slow forward by one node and fast forward by two nodes.
  • Continue only while fast and fast.next are both not null.
  • By the time fast reaches the end, slow will be sitting exactly on the middle node, since it has traveled at half the speed.
▼ Solution & Explanation
class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
    }
}

class SinglyLinkedList {
    Node head;

    void add(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            return;
        }
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
    }

    int findMiddle() {
        Node slow = head;
        Node fast = head;

        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow.data;
    }
}

public class Main {
    public static void main(String[] args) {
        SinglyLinkedList list = new SinglyLinkedList();
        for (int i = 1; i <= 7; i++) {
            list.add(i);
        }

        System.out.println("Middle element: " + list.findMiddle());
    }
}Code language: Java (java)

Explanation:

  • fast = fast.next.next;: Advances the fast pointer twice as fast as the slow pointer on every iteration.
  • while (fast != null && fast.next != null): Stops the loop the moment fast reaches or passes the last node, preventing a NullPointerException on fast.next.next.
  • return slow.data;: Because slow only advances one node per loop while fast advances two, slow naturally lands on the middle node once fast finishes traversing the whole list.

Exercise 23: Cycle Detection

Problem Statement: Write an algorithm to detect if a custom LinkedList contains a loop or cycle (Floyd’s Cycle-Finding Algorithm).

Purpose: This exercise applies the fast and slow pointer technique to a different problem, detecting whether a list loops back on itself instead of ending in null, which would otherwise cause an infinite traversal.

Given Input: A list where the last node's next reference is manually set back to an earlier node, creating a cycle.

Expected Output: Cycle detected: true

▼ Hint
  • Use the same slow and fast pointer setup as the middle element exercise, both starting at the head.
  • Move slow one step and fast two steps on every iteration.
  • If the two pointers ever become equal to each other inside the loop, a cycle exists.
  • If fast or fast.next reaches null, the list has a normal end and no cycle exists.
▼ Solution & Explanation
class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
    }
}

class SinglyLinkedList {
    Node head;

    void add(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            return;
        }
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
    }

    boolean hasCycle() {
        Node slow = head;
        Node fast = head;

        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }
}

public class Main {
    public static void main(String[] args) {
        SinglyLinkedList list = new SinglyLinkedList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

        // Manually create a cycle: last node points back to the third node
        Node third = list.head.next.next;
        Node last = list.head.next.next.next.next;
        last.next = third;

        System.out.println("Cycle detected: " + list.hasCycle());
    }
}Code language: Java (java)

Explanation:

  • last.next = third;: Manually rewires the last node to point back into the middle of the list, forming a loop that would otherwise never occur naturally.
  • slow == fast: Because fast moves twice as fast as slow inside a loop, it eventually laps slow and the two references end up pointing at the same node.
  • No cycle case: If the list had no cycle, fast would eventually reach null, causing the while condition to fail and the method to return false before slow and fast could ever meet.

Exercise 24: Remove Duplicates

Problem Statement: Remove duplicate nodes from an unsorted custom LinkedList without using extra memory.

Purpose: This exercise practices an in-place duplicate removal technique using a nested pointer scan, useful when a HashSet or similar auxiliary structure is off the table due to memory constraints.

Given Input: List: 5 -> 3 -> 5 -> 9 -> 3 -> 8

Expected Output: 5 -> 3 -> 9 -> 8

▼ Hint
  • Use two pointers: an outer current pointer that visits each node once, and an inner runner pointer that checks every node after it.
  • For each current node, have runner scan the rest of the list looking for any node whose data matches current.data.
  • When a match is found, skip over it by pointing runner.next directly to runner.next.next, removing it from the list without allocating any new data structure.
  • This approach runs in O(n squared) time but uses no extra memory beyond the two pointers.
▼ Solution & Explanation
class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
    }
}

class SinglyLinkedList {
    Node head;

    void add(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            return;
        }
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
    }

    void removeDuplicates() {
        Node current = head;

        while (current != null) {
            Node runner = current;
            while (runner.next != null) {
                if (runner.next.data == current.data) {
                    runner.next = runner.next.next;
                } else {
                    runner = runner.next;
                }
            }
            current = current.next;
        }
    }

    void printList() {
        Node temp = head;
        StringBuilder sb = new StringBuilder();
        while (temp != null) {
            sb.append(temp.data);
            if (temp.next != null) {
                sb.append(" -> ");
            }
            temp = temp.next;
        }
        System.out.println(sb);
    }
}

public class Main {
    public static void main(String[] args) {
        SinglyLinkedList list = new SinglyLinkedList();
        list.add(5);
        list.add(3);
        list.add(5);
        list.add(9);
        list.add(3);
        list.add(8);

        list.removeDuplicates();
        list.printList();
    }
}Code language: Java (java)

Explanation:

  • Node runner = current;: Resets the inner scanning pointer to start right at current for every new outer iteration.
  • if (runner.next.data == current.data): Checks whether the node just ahead of runner holds the same value already seen at current.
  • runner.next = runner.next.next;: Removes the duplicate node by relinking around it, without ever advancing runner past the node it just deleted.
  • current = current.next;: Only happens in the outer loop, moving on to check the next distinct value once every duplicate of the current value has been removed from the rest of the list.

Exercise 25: Merge Two Sorted Lists

Problem Statement: Merge two separate, sorted custom LinkedLists into a single, seamless sorted LinkedList.

Purpose: This exercise practices merging two already-sorted sequences by comparing their nodes one at a time and relinking pointers, the same core idea used in the merge step of merge sort.

Given Input: List1: 1 -> 3 -> 5, List2: 2 -> 4 -> 6

Expected Output: 1 -> 2 -> 3 -> 4 -> 5 -> 6

▼ Hint
  • Create a dummy starting node to simplify handling the head of the merged list, then use a separate tail pointer to build the result.
  • While both lists still have remaining nodes, compare their current values and attach the smaller one to tail, then advance that list’s pointer.
  • Once one list is exhausted, attach whatever remains of the other list directly to tail.next, since it is already sorted.
  • Return dummy.next as the head of the merged list, skipping over the placeholder dummy node itself.
▼ Solution & Explanation
class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
    }
}

class SinglyLinkedList {
    Node head;

    void add(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            return;
        }
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
    }

    static Node mergeSorted(Node head1, Node head2) {
        Node dummy = new Node(0);
        Node tail = dummy;

        while (head1 != null && head2 != null) {
            if (head1.data <= head2.data) {
                tail.next = head1;
                head1 = head1.next;
            } else {
                tail.next = head2;
                head2 = head2.next;
            }
            tail = tail.next;
        }

        tail.next = (head1 != null) ? head1 : head2;

        return dummy.next;
    }

    static void printList(Node node) {
        StringBuilder sb = new StringBuilder();
        while (node != null) {
            sb.append(node.data);
            if (node.next != null) {
                sb.append(" -> ");
            }
            node = node.next;
        }
        System.out.println(sb);
    }
}

public class Main {
    public static void main(String[] args) {
        SinglyLinkedList list1 = new SinglyLinkedList();
        list1.add(1);
        list1.add(3);
        list1.add(5);

        SinglyLinkedList list2 = new SinglyLinkedList();
        list2.add(2);
        list2.add(4);
        list2.add(6);

        Node merged = SinglyLinkedList.mergeSorted(list1.head, list2.head);
        SinglyLinkedList.printList(merged);
    }
}Code language: Java (java)

Explanation:

  • Node dummy = new Node(0);: Acts as a placeholder node that makes it easier to build the merged list, since it avoids special-casing the very first node that gets attached.
  • if (head1.data <= head2.data): Compares the current front values of both lists and always attaches the smaller one next, which is what keeps the merged result sorted.
  • tail.next = (head1 != null) ? head1 : head2;: Once one list runs out, the remainder of the other list is already sorted, so it can be attached in a single step instead of being looped through node by node.
  • return dummy.next;: Skips past the placeholder node and returns the true head of the newly merged list.

Filed Under: Java Exercises

Did you find this page helpful? Let others know about it. Sharing helps me continue to create free Python resources.

TweetF  sharein  shareP  Pin

About Vishal

I’m Vishal Hule, the Founder of PYnative.com. As a Python developer, I enjoy assisting students, developers, and learners. Follow me on Twitter.

Related Tutorial Topics:

Java Exercises

All Coding Exercises:

C Exercises
C++ Exercises
Python Exercises
Java Exercises
C# Exercises

Python Exercises and Quizzes

Free coding exercises and quizzes cover Python basics, data structure, data analytics, and more.

  • 15+ Topic-specific Exercises and Quizzes
  • Each Exercise contains 25+ questions
  • Each Quiz contains 25 MCQ
Exercises
Quizzes

Leave a Reply Cancel reply

your email address will NOT be published. all comments are moderated according to our comment policy.

Use <pre> tag for posting code. E.g. <pre> Your entire code </pre>

In: Java Exercises
TweetF  sharein  shareP  Pin

  Java Exercises

  • All Java Exercises
  • Java Exercise for Beginners
  • Java Loops Exercise
  • Java String Exercise
  • Java ArrayList Exercise
  • Java LinkedList Exercise
  • Java HashMap and TreeMap Exercise
  • Java HashSet and TreeSet Exercise
  • Java OOP Exercise
  • Java Methods Exercise
  • Java Enums Exercise
  • Java Exception Handling Exercise
  • Java File Handling Exercise
  • Java Date and Time Exercise
  • Java Data Structures Exercise
  • Java Sorting and Searching Exercise
  • Java Lambda and Functional Interfaces Exercise
  • Java Regex Exercise
  • Java Random Data Generation Exercise
  • Java Generics Exercise
  • Java Reflection Exercise
  • Java JDBC Exercise

All Coding Exercises

Python Exercises C Exercises C++ Exercises Java Exercises C# Exercises

About PYnative

PYnative.com is for Python lovers. Here, You can get Tutorials, Exercises, and Quizzes to practice and improve your Python skills.

Follow Us

To get New Python Tutorials, Exercises, and Quizzes

  • Twitter
  • Facebook
  • Sitemap

Explore Python

  • Learn Python
  • Python Basics
  • Python Databases
  • Python Exercises
  • Python Quizzes
  • Online Python Code Editor
  • Python Tricks

Coding Exercises

  • C Exercises
  • C++ Exercises
  • Python Exercises
  • Java Exercises
  • C# Exercises

Legal Stuff

  • About Us
  • Contact Us

We use cookies to improve your experience. While using PYnative, you agree to have read and accepted our:

  • Terms Of Use
  • Privacy Policy
  • Cookie Policy

Copyright © 2018–2026 pynative.com