Back to Data Structures & Algorithms
2026-03-256 min read

Array vs linked list: when each wins (Data Structures & Algorithms)

Learn Array vs linked list: when each wins (Data Structures & Algorithms) step by step with clear examples and exercises.

Why This Matters

In this full guide, we delve into the intricacies of arrays and linked lists - two fundamental data structures used extensively in computer science for organizing and storing data efficiently. Mastering these concepts will empower you to make informed decisions when designing algorithms, optimizing code, and solving complex problems. Additionally, being able to identify and debug common mistakes is crucial during interviews and coding competitions.

Prerequisites

To fully grasp this lesson, you should have a good understanding of the following concepts:

  • Basic Python syntax (variables, loops, functions)
  • Data types (integers, strings, lists)
  • Functions like len(), append(), and slicing
  • Recursion
  • Time complexity analysis

Additional Resources

Core Concept

Arrays

An array is a collection of elements, each identified by an index. In Python, arrays are often referred to as lists. They have a fixed size, and elements can be accessed using their position in the list. Here's an example:

my_array = [1, 2, 3, 4]
print(my_array[0]) # Output: 1
print(len(my_array)) # Output: 4

Advantages of Arrays:

  • Fast access to elements by index (constant time O(1))
  • Easy to implement and use
  • Support for various data types (integers, strings, etc.)
  • Built-in functions like append(), insert(), pop(), and slicing make it convenient to manipulate the array

Disadvantages of Arrays:

  • Fixed size: resizing an array requires creating a new one and copying the contents, which can be slow
  • Elements may overlap if not properly initialized, leading to unexpected behavior
  • Accessing elements at the end of a large list is slower due to the need to traverse through all preceding elements (O(n))

Linked Lists

A linked list is a collection of nodes, where each node contains data and a reference (pointer) to the next node. Unlike arrays, linked lists have dynamic size, allowing elements to be added or removed efficiently. Here's an example implementation of a singly-linked list in Python:

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

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

def append(self, data):
if not self.head:
self.head = Node(data)
else:
current = self.head
while current.next:
current = current.next
current.next = Node(data)

def insert_at(self, index, data):
if index < 0 or index > len(self._get_length()):
raise IndexError("Index out of range")

if index == 0:
self.head = Node(data)
self.head.next = self.head
return

current = self.head
for _ in range(index - 1):
if not current.next:
raise IndexError("Index out of range")
current = current.next

new_node = Node(data)
new_node.next = current.next
current.next = new_node

def _get_length(self):
count = 0
current = self.head
while current:
count += 1
current = current.next
return count

Advantages of Linked Lists:

  • Dynamic size: elements can be added or removed efficiently without reallocating memory
  • No need to resize the list when adding new elements
  • Accessing the last element is faster due to constant time O(1) access to the previous node (when traversing from the end)

Disadvantages of Linked Lists:

  • Slower access to elements by index (linear time O(n)) due to traversing the nodes
  • More complex implementation and slower operations compared to arrays for simple tasks
  • Memory fragmentation can occur when deleting nodes, making memory management more difficult

Worked Example

Let's implement a function that finds the intersection of two sorted linked lists.

def find_intersection(list1, list2):

Keep track of both lists' current nodes

node1 = list1.head

node2 = list2.head

If either list is empty, return None

if not node1 or not node2:

return None

Compare the current nodes until we find a common element

while node1 and node2:

if node1.data == node2.data:

return node1.data

elif node1.data < node2.data:

node1 = node1.next

else:

node2 = node2.next

If no common element is found, return None

return None

Common Mistakes

Arrays:

  • Forgetting to initialize an array before using it (Python automatically initializes lists with empty elements)
  • Indexing out of bounds when accessing elements outside the array's range
  • Modifying a list while iterating over it, leading to unexpected behavior
  • Not considering edge cases like empty arrays or arrays with only one element

Linked Lists:

  • Creating a cycle in the linked list by making a node's next pointer point back to itself or another node in the list
  • Forgetting to initialize a new node when adding an element to the end of the list
  • Accessing elements by index using a loop, which results in traversing the nodes (O(n)) instead of accessing them directly (O(1))
  • Not considering edge cases like empty lists or lists with only one element

Practice Questions

  1. Write a function that finds the second occurrence of an element in a sorted array if it exists. If the element does not exist, return -1.
def find_second(arr, target):
if len(arr) < 2:
return -1

left = 0
right = len(arr) - 1

while left <= right:
mid = (left + right) // 2
if arr[mid] == target and mid > 0 and arr[mid-1] == target:
return arr[mid]
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1

return -1
  1. Implement a function that merges two sorted linked lists into one sorted linked list.
def merge_lists(list1, list2):
result = LinkedList()

node1 = list1.head
node2 = list2.head

while node1 and node2:
if node1.data < node2.data:
result.append(node1.data)
node1 = node1.next
else:
result.append(node2.data)
node2 = node2.next

Append any remaining nodes from either list

if node1:

result.head = node1

elif node2:

result.head = node2

return result


3. Given a singly-linked list with cycles, write a function that detects the cycle and returns the starting node of the cycle. If there is no cycle, return None.

def find_cycle_start(list):

slow = fast = list.head

while fast and fast.next:

slow = slow.next

fast = fast.next.next

if slow == fast:

break

if not slow or not fast:

return None

slow = list.head

while slow != fast:

slow = slow.next

fast = fast.next

slow = slow.next

return fast

FAQ

Q: Why not use an array for dynamic size data structures like linked lists?

A: Arrays have a fixed size, which makes them less efficient for dynamic size data structures like linked lists. Linked lists, on the other hand, can easily accommodate new elements without reallocating memory.

Q: Can I implement a linked list in Python using arrays instead of nodes and pointers?

A: While it's technically possible to simulate a linked list using arrays, this approach would lose many of the benefits of linked lists, such as dynamic size and efficient insertion/deletion.

Q: What is the time complexity of accessing an element in a Python list (array) by index?

A: Accessing an element by index in a Python list has a constant time complexity O(1), assuming that the index is within the bounds of the list. However, accessing elements at the end of a large list can be slower due to the need to traverse through all preceding elements (O(n)).

Q: Why does traversing a linked list take linear time O(n) when accessing an element by index?

A: Traversing a linked list takes linear time O(n) because we need to visit each node in the list until we reach the desired position. On the other hand, accessing an element by index in an array is constant time O(1), as we can directly access the memory location of the element using its index.

Q: Why is it more efficient to access the last element of a linked list when traversing from the end?

A: Accessing the last element of a linked list when traversing from the end is faster because, on average, we only need to traverse half of the nodes in the list. This is due to the fact that the previous node is always available, allowing us to quickly move to the next-to-last node and so on until reaching the last node.

Q: What are some real-world applications of arrays and linked lists?

A: Arrays and linked lists have numerous applications in various fields such as databases, operating systems, compilers, and computer graphics. For example, arrays are commonly used to store data structures like matrices, while linked lists are used for dynamic memory allocation, implementing stacks, queues, and doubly-linked lists.

Array vs linked list: when each wins (Data Structures & Algorithms) | Data Structures & Algorithms | XQA Learn