Intermediate

LinkedList Basic Operations

Five essential linked list problems that appear in almost every coding interview. Master these and you will have the foundation for all advanced linked list challenges.

Problem 1: Reverse Linked List (LC 206)

Problem: Given the head of a singly linked list, reverse the list and return the reversed list.

# Before:  1 -> 2 -> 3 -> 4 -> 5 -> None
# After:   5 -> 4 -> 3 -> 2 -> 1 -> None
#
# Step-by-step pointer manipulation:
#
# Step 1:  prev=None  curr=1 -> 2 -> 3 -> 4 -> 5
#          None <- 1    2 -> 3 -> 4 -> 5
#
# Step 2:  None <- 1 <- 2    3 -> 4 -> 5
#
# Step 3:  None <- 1 <- 2 <- 3    4 -> 5
#
# Step 4:  None <- 1 <- 2 <- 3 <- 4    5
#
# Step 5:  None <- 1 <- 2 <- 3 <- 4 <- 5  (done, prev = 5)

def reverseList(head):
    """Reverse a singly linked list iteratively.

    Strategy: Maintain three pointers (prev, curr, next_node).
    At each step, reverse curr's pointer to point to prev.

    Time:  O(n) - visit each node once
    Space: O(1) - only three pointers
    """
    prev = None
    curr = head

    while curr:
        next_node = curr.next   # save next
        curr.next = prev        # reverse pointer
        prev = curr             # advance prev
        curr = next_node        # advance curr

    return prev  # new head


def reverseList_recursive(head):
    """Reverse a singly linked list recursively.

    Base case: empty list or single node.
    Recursive case: reverse the rest, then fix pointers.

    Time:  O(n)
    Space: O(n) - call stack depth
    """
    if not head or not head.next:
        return head

    new_head = reverseList_recursive(head.next)
    head.next.next = head  # point next node back to us
    head.next = None       # remove old forward pointer

    return new_head

Problem 2: Middle of Linked List (LC 876)

Problem: Given the head of a singly linked list, return the middle node. If two middle nodes, return the second one.

# Example: 1 -> 2 -> 3 -> 4 -> 5 -> None
#                     ^
#                   middle (node 3)
#
# Fast/Slow pointer technique:
#
# Step 0:  slow=1, fast=1
# Step 1:  slow=2, fast=3
# Step 2:  slow=3, fast=5
# fast.next is None -> stop. slow = middle!
#
# Even length: 1 -> 2 -> 3 -> 4 -> None
# Step 0:  slow=1, fast=1
# Step 1:  slow=2, fast=3
# Step 2:  slow=3, fast=None (fast is None -> stop)
# Returns second middle (node 3)

def middleNode(head):
    """Find the middle node using slow/fast pointers.

    Slow moves 1 step, fast moves 2 steps.
    When fast reaches the end, slow is at the middle.

    Time:  O(n) - single pass
    Space: O(1) - two pointers
    """
    slow = fast = head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

    return slow

Problem 3: Linked List Cycle (LC 141)

Problem: Given the head of a linked list, determine if it has a cycle.

# Cycle example:
#
#   1 -> 2 -> 3 -> 4
#             ^    |
#             |    v
#             6 <- 5
#
# Floyd's Cycle Detection (Tortoise and Hare):
#
# Step 0: slow=1, fast=1
# Step 1: slow=2, fast=3
# Step 2: slow=3, fast=5
# Step 3: slow=4, fast=3  (fast looped!)
# Step 4: slow=5, fast=5  -> MEET! Cycle detected.
#
# No cycle:
#   1 -> 2 -> 3 -> None
#   fast reaches None -> no cycle

def hasCycle(head):
    """Detect cycle using Floyd's algorithm.

    If there is a cycle, slow and fast will eventually meet.
    If no cycle, fast will reach None.

    Time:  O(n) - at most 2n steps
    Space: O(1) - two pointers
    """
    slow = fast = head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            return True

    return False


def detectCycle(head):
    """Find the node where the cycle begins (LC 142).

    After slow and fast meet, reset one pointer to head.
    Move both one step at a time. They meet at cycle start.

    Time:  O(n)
    Space: O(1)
    """
    slow = fast = head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            # Reset slow to head, move both at speed 1
            slow = head
            while slow != fast:
                slow = slow.next
                fast = fast.next
            return slow  # cycle start

    return None  # no cycle

Problem 4: Merge Two Sorted Lists (LC 21)

Problem: Merge two sorted linked lists into one sorted list.

# List1: 1 -> 2 -> 4 -> None
# List2: 1 -> 3 -> 4 -> None
#
# Merge process (using dummy node):
#
# dummy -> ?
# Compare 1 vs 1: pick list1's 1
# dummy -> 1 -> ?
# Compare 2 vs 1: pick list2's 1
# dummy -> 1 -> 1 -> ?
# Compare 2 vs 3: pick 2
# dummy -> 1 -> 1 -> 2 -> ?
# Compare 4 vs 3: pick 3
# dummy -> 1 -> 1 -> 2 -> 3 -> ?
# Compare 4 vs 4: pick list1's 4
# dummy -> 1 -> 1 -> 2 -> 3 -> 4 -> ?
# list1 exhausted, append rest of list2
# dummy -> 1 -> 1 -> 2 -> 3 -> 4 -> 4 -> None

def mergeTwoLists(list1, list2):
    """Merge two sorted linked lists.

    Use a dummy node and compare heads of both lists.
    Append the smaller node each time.

    Time:  O(n + m) where n, m are list lengths
    Space: O(1) - reuse existing nodes
    """
    dummy = ListNode(0)
    tail = dummy

    while list1 and list2:
        if list1.val <= list2.val:
            tail.next = list1
            list1 = list1.next
        else:
            tail.next = list2
            list2 = list2.next
        tail = tail.next

    # Attach remaining nodes
    tail.next = list1 if list1 else list2

    return dummy.next

Problem 5: Remove Duplicates from Sorted List (LC 83)

Problem: Given the head of a sorted linked list, delete all duplicates so each element appears only once.

# Before: 1 -> 1 -> 2 -> 3 -> 3 -> None
# After:  1 -> 2 -> 3 -> None
#
# Walk through:
#   curr = 1, curr.next = 1 (duplicate!) -> skip
#   1 -> 2 -> 3 -> 3
#   curr = 1, curr.next = 2 (different) -> advance
#   curr = 2, curr.next = 3 (different) -> advance
#   curr = 3, curr.next = 3 (duplicate!) -> skip
#   1 -> 2 -> 3 -> None
#   curr = 3, curr.next = None -> done

def deleteDuplicates(head):
    """Remove duplicates from a sorted linked list.

    Since the list is sorted, duplicates are adjacent.
    Skip duplicate nodes by adjusting next pointers.

    Time:  O(n) - single pass
    Space: O(1) - in-place
    """
    curr = head

    while curr and curr.next:
        if curr.val == curr.next.val:
            curr.next = curr.next.next  # skip duplicate
        else:
            curr = curr.next            # move forward

    return head

Complexity Summary

ProblemTimeSpaceKey Technique
Reverse Linked ListO(n)O(1)Three-pointer swap
Middle of ListO(n)O(1)Slow/fast pointers
Detect CycleO(n)O(1)Floyd's algorithm
Merge Two SortedO(n+m)O(1)Dummy node + compare
Remove DuplicatesO(n)O(1)Skip adjacent duplicates
Interview Tip: These five problems form the building blocks for every harder linked list problem. Reverse is used in "Reverse Nodes in K-Group," slow/fast is used in "Sort List" (merge sort), and merge is used in "Merge K Sorted Lists." Master these patterns first.