Skip to content

98. Odd Even Linked List

๐Ÿ”— LeetCode Problem: 328. Odd Even Linked List
๐Ÿ“Š Difficulty: Medium
๐Ÿท๏ธ Topics: Linked List

Problem Statement

Given the head of a singly linked list, group all the nodes with odd indices together followed by the nodes with even indices, and return the reordered list.

The first node is considered odd, and the second node is even, and so on.

Note that the relative order inside both the even and odd groups should remain as it was in the input.

You must solve the problem in O(1) extra space complexity and O(n) time complexity.

Example 1:

Input: head = [1,2,3,4,5]
Output: [1,3,5,2,4]

Visual:
Original: 1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5 โ†’ null
          โ†‘   โ†‘   โ†‘   โ†‘   โ†‘
        odd even odd even odd

Reordered: 1 โ†’ 3 โ†’ 5 โ†’ 2 โ†’ 4 โ†’ null
           โ†‘___โ†‘___โ†‘   โ†‘___โ†‘
           odd nodes   even nodes

Example 2:

Input: head = [2,1,3,5,6,4,7]
Output: [2,3,6,7,1,5,4]

Visual:
Original: 2 โ†’ 1 โ†’ 3 โ†’ 5 โ†’ 6 โ†’ 4 โ†’ 7 โ†’ null
          โ†‘   โ†‘   โ†‘   โ†‘   โ†‘   โ†‘   โ†‘
         odd even odd even odd even odd

Reordered: 2 โ†’ 3 โ†’ 6 โ†’ 7 โ†’ 1 โ†’ 5 โ†’ 4 โ†’ null
           โ†‘___โ†‘___โ†‘___โ†‘   โ†‘___โ†‘___โ†‘
           odd positions   even positions

Constraints: - The number of nodes in the linked list is in the range [0, 10^4]. - -10^6 <= Node.val <= 10^6


๐ŸŒŸ ELI5: The Simple Idea!

Think of separating kids by position in line:

Original line: [1, 2, 3, 4, 5]
                โ†‘  โ†‘  โ†‘  โ†‘  โ†‘
              pos1 2  3  4  5

Task: Odd positions first, then even positions

Odd positions (1, 3, 5): [1, 3, 5]
Even positions (2, 4):   [2, 4]

New line: [1, 3, 5] + [2, 4] = [1, 3, 5, 2, 4] โœ“

Key Insight: Build two separate chains, then connect!

Original: 1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5

Build odd chain:  1 โ†’ 3 โ†’ 5
Build even chain: 2 โ†’ 4

Connect: 1 โ†’ 3 โ†’ 5 โ†’ 2 โ†’ 4 โœ“

๐ŸŽจ Visual Understanding

The Separation Process

Original: 1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5 โ†’ null

Step by step:

Initial:
  odd = 1, even = 2, evenHead = 2

  1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5 โ†’ null
  โ†‘   โ†‘
  odd even

Iteration 1:
  odd.next = even.next (3)
  1 โ†’ 3 โ†’ 4 โ†’ 5 โ†’ null
      โ†‘
  odd moves to 3

  even.next = odd.next (4)
  2 โ†’ 4 โ†’ null
      โ†‘
  even moves to 4

  State:
    Odd chain:  1 โ†’ 3 โ†’ 5
    Even chain: 2 โ†’ 4

Iteration 2:
  odd.next = even.next (5)
  1 โ†’ 3 โ†’ 5 โ†’ null
          โ†‘
  odd moves to 5

  even.next = odd.next (null)
  2 โ†’ 4 โ†’ null

  even is null, exit loop

Final: Connect odd chain to even chain
  odd.next = evenHead
  1 โ†’ 3 โ†’ 5 โ†’ 2 โ†’ 4 โ†’ null โœ“

๐ŸŽฏ Approach: Two Pointers (Odd & Even) โญ

The Optimal Solution

Algorithm:

1. Create two pointers: odd and even
2. Save even head (to connect later)
3. While even and even.next exist:
   - odd.next = even.next (skip even)
   - odd = odd.next (move odd)
   - even.next = odd.next (skip odd)
   - even = even.next (move even)
4. Connect: odd.next = evenHead

Implementation

/**
 * Two-pointer approach: separate odd and even chains
 * Time: O(n), Space: O(1)
 */
public ListNode oddEvenList(ListNode head) {
    // Edge cases
    if (head == null || head.next == null) {
        return head;
    }

    // Initialize pointers
    ListNode odd = head;
    ListNode even = head.next;
    ListNode evenHead = even;  // Save even head for later connection

    // Separate odd and even nodes
    while (even != null && even.next != null) {
        // Connect odd nodes
        odd.next = even.next;
        odd = odd.next;

        // Connect even nodes
        even.next = odd.next;
        even = even.next;
    }

    // Connect odd chain to even chain
    odd.next = evenHead;

    return head;
}

โฐ Time: O(n) - Single pass through the list
๐Ÿ’พ Space: O(1) - Only three pointers

๐Ÿ” Super Detailed Dry Run

Example: head = [1, 2, 3, 4, 5]

Goal: Reorder to [1, 3, 5, 2, 4]

Initial state:
  head โ†’ 1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5 โ†’ null

  odd = head = 1
  even = head.next = 2
  evenHead = even = 2

State:
  1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5 โ†’ null
  โ†‘   โ†‘
  odd even
  evenHead = 2

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
Iteration 1
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Condition: even != null (2) && even.next != null (3) โœ“

Step 1: Connect odd nodes
  odd.next = even.next
  1.next = 3

  Before:
    1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5

  After:
    1 โ”€โ”€โ”€โ”€โ”€โ”€โ†’ 3 โ†’ 4 โ†’ 5
        2 โ†’ 3

  Move odd:
    odd = odd.next = 3

Step 2: Connect even nodes
  even.next = odd.next
  2.next = 4

  Before:
    2 โ†’ 3 โ†’ 4

  After:
    2 โ”€โ”€โ”€โ”€โ”€โ”€โ†’ 4 โ†’ 5
        3 โ†’ 4

  Move even:
    even = even.next = 4

State after iteration 1:
  Odd chain:  1 โ†’ 3 โ†’ 4 โ†’ 5
                  โ†‘
                  odd

  Even chain: 2 โ†’ 4 โ†’ 5
                  โ†‘
                 even

  evenHead still points to 2

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
Iteration 2
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Condition: even != null (4) && even.next != null (5) โœ“

Step 1: Connect odd nodes
  odd.next = even.next
  3.next = 5

  Before:
    1 โ†’ 3 โ†’ 4 โ†’ 5

  After:
    1 โ†’ 3 โ”€โ”€โ”€โ”€โ”€โ”€โ†’ 5 โ†’ null
            4 โ†’ 5

  Move odd:
    odd = odd.next = 5

Step 2: Connect even nodes
  even.next = odd.next
  4.next = null (5.next is null)

  Before:
    2 โ†’ 4 โ†’ 5

  After:
    2 โ†’ 4 โ†’ null

  Move even:
    even = even.next = null

State after iteration 2:
  Odd chain:  1 โ†’ 3 โ†’ 5 โ†’ null
                      โ†‘
                     odd

  Even chain: 2 โ†’ 4 โ†’ null
                      โ†‘
                    even

  evenHead still points to 2

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
Loop Exit & Connect
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Condition: even != null (null) โœ—

Exit loop!

Connect odd and even chains:
  odd.next = evenHead
  5.next = 2

  1 โ†’ 3 โ†’ 5 โ†’ 2 โ†’ 4 โ†’ null

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
Return Result
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Return: head (node 1)

Final list: 1 โ†’ 3 โ†’ 5 โ†’ 2 โ†’ 4 โ†’ null โœ“

Result: [1, 3, 5, 2, 4]

Example 2: head = [1, 2, 3, 4]

Even length example

Initial:
  odd = 1, even = 2, evenHead = 2

  1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ null
  โ†‘   โ†‘
  odd even

Iteration 1:
  odd.next = 3
  odd = 3
  even.next = 4
  even = 4

  Odd:  1 โ†’ 3 โ†’ 4
  Even: 2 โ†’ 4

Iteration 2:
  Condition: even (4) && even.next (null) โœ—
  Exit!

Connect:
  odd.next = evenHead
  3.next = 2

  1 โ†’ 3 โ†’ 2 โ†’ 4 โ†’ null โœ“

Works for even length too!

๐ŸŽฏ Why This Algorithm Works

The Two-Chain Concept

At each step, we're building two independent chains:

Original: 1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5

Odd chain construction:
  Start: 1
  Add:   1 โ†’ 3 (skip 2)
  Add:   1 โ†’ 3 โ†’ 5 (skip 4)

Even chain construction:
  Start: 2
  Add:   2 โ†’ 4 (skip 3)
  End:   2 โ†’ 4 โ†’ null (skip 5)

Then connect: odd.next = evenHead

Why Save evenHead?

Without saving:
  even pointer moves through the chain
  At the end, even = null (or last even node)
  We lose reference to first even node!
  Can't connect! โŒ

With evenHead:
  evenHead always points to first even node (2)
  even pointer can move freely
  At the end: odd.next = evenHead โœ“

Loop Condition Explained

while (even != null && even.next != null)

Why both conditions?

even != null:
  If list has odd length, even becomes null
  [1, 2, 3] โ†’ even moves 2 โ†’ null

even.next != null:
  If list has even length, even.next becomes null
  [1, 2, 3, 4] โ†’ even at 4, even.next = null

Both ensure we don't access null.next!

โš ๏ธ Common Mistakes

Mistake 1: Not saving evenHead

// โŒ WRONG - Lost reference to even chain!
ListNode odd = head;
ListNode even = head.next;
// Forgot: ListNode evenHead = even;

while (...) {
    // even pointer moves
}

odd.next = even;  // even might be null or wrong node!

// โœ“ CORRECT - Save before moving
ListNode evenHead = even;
// ...
odd.next = evenHead;

Mistake 2: Wrong loop condition

// โŒ WRONG - Can cause null pointer exception
while (even != null) {
    odd.next = even.next;  // What if even.next is null?
}

// โœ“ CORRECT - Check both
while (even != null && even.next != null) {
    // Safe to access even.next
}

Mistake 3: Moving pointers before updating next

// โŒ WRONG - Lost reference!
odd = odd.next;  // Moved too early!
odd.next = even.next;  // Wrong odd!

// โœ“ CORRECT - Update next first, then move
odd.next = even.next;
odd = odd.next;

Mistake 4: Trying to create new nodes

// โŒ WRONG - Wastes space, not in-place
ListNode oddList = new ListNode(0);
ListNode evenList = new ListNode(0);
// ... build new lists ...

// โœ“ CORRECT - Reuse existing nodes
// Just rearrange pointers!

Mistake 5: Forgetting to connect chains

// โŒ WRONG - Two separate chains!
while (...) {
    // Build odd and even chains
}
// Forgot: odd.next = evenHead

return head;  // Only returns odd chain!

// โœ“ CORRECT - Connect them
odd.next = evenHead;
return head;


๐ŸŽฏ Pattern Recognition

Problem Type: Reorder by Position (Odd/Even)
Core Pattern: Two-Pointer Separation

When to Apply:
โœ“ Group by position (odd/even)
โœ“ Reorder while maintaining relative order
โœ“ Separate into two groups
โœ“ In-place rearrangement

Recognition Keywords:
- "odd indices"
- "even indices"
- "group by position"
- "maintain relative order"
- "O(1) space"

Similar Problems:
- Partition List (LC 86) - Separate by value
- Reorder List (LC 143) - Different pattern
- Split Linked List in Parts (LC 725) - Multiple groups

Key Components:
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Two Pointers: odd and even                โ”‚
โ”‚ Save Head: evenHead for connection        โ”‚
โ”‚ Build Chains: Skip alternating nodes      โ”‚
โ”‚ Connect: odd.next = evenHead              โ”‚
โ”‚ Time: O(n), Space: O(1)                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿง  Interview Strategy

Step 1: "I need to separate odd and even positioned nodes"
Step 2: "I'll use two pointers to build separate chains"
Step 3: "Then connect odd chain to even chain"

Key Points to Mention:
- Two pointers: one for odd, one for even
- Save even head before moving pointers
- Skip alternating nodes to build chains
- Maintain relative order automatically
- Connect chains at the end
- Time: O(n), Space: O(1) in-place

Walk Through Example:
"For [1,2,3,4,5]:
 Start: odd=1, even=2, save evenHead=2
 Iteration 1: 
   odd.next = 3 (skip 2)
   even.next = 4 (skip 3)
 Iteration 2:
   odd.next = 5 (skip 4)
   even.next = null
 Connect: 5.next = evenHead (2)
 Result: [1,3,5,2,4]"

Why Two Pointers:
"Each pointer builds its own chain
 by skipping the other type of nodes.
 Odd skips even, even skips odd.
 This maintains relative order automatically."

Edge Cases to Mention:
โœ“ Empty list โ†’ return null
โœ“ Single node โ†’ return as is
โœ“ Two nodes โ†’ swap them
โœ“ Odd length โ†’ last node is odd
โœ“ Even length โ†’ both chains equal

๐Ÿ“ Quick Revision Notes

๐ŸŽฏ Core Concept:

Odd Even Linked List: Use two pointers to build separate chains. Save evenHead before moving! Odd skips even (odd.next = even.next), even skips odd (even.next = odd.next). Loop while even && even.next exist. Finally connect: odd.next = evenHead. O(1) space!

โšก Quick Implementation:

import java.util.Arrays;
import java.util.List;

class ListNode {
  int val;
  ListNode next;
  ListNode() {}
  ListNode(int val) { this.val = val; }
  ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

class Solution {
  public static ListNode create(List<Integer> list) {
    ListNode dummy = new ListNode(-1);
    ListNode curr = dummy;

    for(int num : list) {
      curr.next = new ListNode(num);
      curr = curr.next;
    }

    return dummy.next;
  }

  public static void print(ListNode head) {
    ListNode curr = head;
    while (curr != null) {
      System.out.print(curr.val + " -> ");
      curr = curr.next;
    }

    System.out.println();
  }

  public ListNode oddEvenList(ListNode head) {
    // same for 0/1/2 elements.
    if(head == null || head.next == null || head.next.next == null) {
      return head;
    }

    ListNode odd = head;
    ListNode even = head.next;
    ListNode evenHead = even;

    // Both works.
    // while (odd != null && odd.next != null && even != null && even.next != null) {
    while (even != null && even.next != null) {
      odd.next = even.next;
      odd = odd.next;
      even.next = odd.next;
      even = even.next;
    }

    // Linking odd and even lists.
    odd.next = evenHead;

    return head;
  }

  public static void main(String[] args) {
    Solution t = new Solution();

    ListNode list1 = create(Arrays.asList(1, 2, 3, 4, 5));    
    print(t.oddEvenList(list1));

    print(t.oddEvenList(create(Arrays.asList(-1, 5, 3, 4, 0))));
    print(t.oddEvenList(create(Arrays.asList(0)))); // 1 element
    print(t.oddEvenList(create(Arrays.asList(0, 1)))); // 2 elements
    print(t.oddEvenList(create(Arrays.asList(2, 1)))); // 2 elements
    print(t.oddEvenList(create(Arrays.asList(2, 1, 5)))); // odd count
    print(t.oddEvenList(create(Arrays.asList(2, 1, -4, 0)))); // even count
    print(t.oddEvenList(create(Arrays.asList(1, 2, 3, 4, 5)))); // strictly increasing
    print(t.oddEvenList(create(Arrays.asList(5, 4, 3, 2)))); // strictly decreasing
  }
}

๐Ÿ”‘ Key Insights:

  • Pattern: Two-Pointer Separation
  • Save evenHead: Before moving even pointer
  • Skip pattern: odd โ†’ even.next, even โ†’ odd.next
  • Loop: while even && even.next
  • Connect: odd.next = evenHead (critical!)
  • Time: O(n), Space: O(1) โœ“

๐ŸŽช Memory Aid:

"Two chains, skip between, save and connect!"
"Odd skips even, even skips odd!" โœจ

โš ๏ธ Critical Steps:

1. Save evenHead FIRST
2. Loop: even && even.next
3. Update next BEFORE moving
4. Connect at end: odd.next = evenHead

Without evenHead โ†’ LOST!
Wrong loop โ†’ NULL POINTER!

๐Ÿงช Edge Cases

Case 1: Empty list

Input: head = null
Output: null
Handled: Early return

Case 2: Single node

Input: head = [1]
Output: [1]
Handled: Early return

Case 3: Two nodes

Input: head = [1,2]
Output: [1,2]
Loop doesn't run, already correct

Case 4: Odd length

Input: head = [1,2,3,4,5]
Output: [1,3,5,2,4]
Last node is odd, works correctly

Case 5: Even length

Input: head = [1,2,3,4]
Output: [1,3,2,4]
Both chains equal length, works correctly

All handled perfectly! โœ“


  • Partition List (LC 86) - Separate by value, similar two-pointer
  • Reorder List (LC 143) - Different reordering pattern
  • Split Linked List in Parts (LC 725) - Multiple groups

Happy practicing! ๐ŸŽฏ

Note: This problem teaches the two-pointer separation pattern for linked lists! The key insight is building two independent chains simultaneously by having each pointer skip the other type's nodes. This pattern appears in many partition/grouping problems. Master the "save head, build chains, connect" technique! ๐Ÿ’ชโœจ