0
0
Data-structures-theoryHow-ToBeginner · 4 min read

Time Complexity of Linked List Operations Explained

The time complexity of linked list operations varies: insertion and deletion at the head are O(1), while search and operations at arbitrary positions require O(n) time because you may need to traverse the list. Linked lists do not support direct access by index, so accessing elements is slower than arrays.
📐

Syntax

A linked list consists of nodes where each node contains data and a reference (or pointer) to the next node.

Basic operations include:

  • Insertion at head: Add a new node at the start.
  • Insertion at tail: Add a new node at the end.
  • Deletion at head: Remove the first node.
  • Deletion at tail or arbitrary position: Remove a node after traversal.
  • Search: Find a node by traversing from the head.
python
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class LinkedList:
    def __init__(self):
        self.head = None

    def insert_at_head(self, data):
        new_node = Node(data)
        new_node.next = self.head
        self.head = new_node

    def search(self, key):
        current = self.head
        while current:
            if current.data == key:
                return True
            current = current.next
        return False
💻

Example

This example shows insertion at the head, searching for a value, and deletion at the head in a linked list.

python
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class LinkedList:
    def __init__(self):
        self.head = None

    def insert_at_head(self, data):
        new_node = Node(data)
        new_node.next = self.head
        self.head = new_node

    def delete_at_head(self):
        if self.head is not None:
            self.head = self.head.next

    def search(self, key):
        current = self.head
        while current:
            if current.data == key:
                return True
            current = current.next
        return False

    def print_list(self):
        current = self.head
        while current:
            print(current.data, end=' -> ')
            current = current.next
        print('None')

# Usage
ll = LinkedList()
ll.insert_at_head(10)
ll.insert_at_head(20)
ll.insert_at_head(30)
ll.print_list()  # 30 -> 20 -> 10 -> None
print(ll.search(20))  # True
print(ll.search(40))  # False
ll.delete_at_head()
ll.print_list()  # 20 -> 10 -> None
Output
30 -> 20 -> 10 -> None True False 20 -> 10 -> None
⚠️

Common Pitfalls

One common mistake is assuming linked lists allow fast access by index like arrays. Accessing an element by position requires traversing nodes, which takes O(n) time.

Another pitfall is forgetting to update pointers correctly during insertion or deletion, which can break the list.

Also, deleting the tail node requires traversal from the head to find the previous node, making it O(n).

python
class LinkedList:
    def __init__(self):
        self.head = None

    # Incorrect deletion at tail (does not update previous node's next)
    def delete_at_tail_wrong(self):
        if self.head is None:
            return
        if self.head.next is None:
            self.head = None
            return
        current = self.head
        while current.next:
            current = current.next
        # Missing step: need to find previous node and set its next to None

    # Correct deletion at tail
    def delete_at_tail(self):
        if self.head is None:
            return
        if self.head.next is None:
            self.head = None
            return
        current = self.head
        while current.next.next:
            current = current.next
        current.next = None
📊

Quick Reference

OperationTime Complexity
Insertion at headO(1)
Insertion at tail (with tail pointer)O(1)
Insertion at tail (without tail pointer)O(n)
Deletion at headO(1)
Deletion at tailO(n)
Search (by value)O(n)
Access by indexO(n)

Key Takeaways

Insertion and deletion at the head of a linked list take constant time O(1).
Searching or accessing elements by position requires traversing the list, taking O(n) time.
Without a tail pointer, insertion or deletion at the tail requires O(n) time.
Linked lists do not support direct access by index like arrays.
Careful pointer updates are essential to avoid breaking the linked list structure.