An array is the simplest data structure there is. It’s a contiguous block of memory that stores elements of the same type, one after another. Think of it like a row of lockers in a hallway — each locker has a number (index) and holds one item.
The reason arrays are so fundamental is that almost every other data structure is built on top of them. Stacks, queues, heaps, hash tables — they all use arrays under the hood.
How Arrays Work in Memory
When we create an array of size 5, the computer reserves 5 consecutive memory slots. Because the slots are next to each other, the computer can jump to any element instantly using math: address = base_address + (index × element_size).
This is why accessing an element by index is O(1) — the computer doesn’t need to search. It just calculates the address and goes straight there.
Static vs Dynamic Arrays
Static arrays have a fixed size decided at creation time. Once we say “give me an array of size 10,” that’s it. We can’t make it bigger. C and Java (with int[]) use static arrays.
Dynamic arrays can grow and shrink. When the internal array fills up, it creates a new array (usually 2x the size), copies everything over, and ditches the old one. This resize is O(n), but it happens so rarely that the amortized cost of appending is still O(1).
JavaScript’s Array, Python’s list, and Java’s ArrayList are all dynamic arrays.
Common Operations & Time Complexities
| Operation | Time Complexity | Why |
|---|---|---|
| Access by index | O(1) | Direct address calculation |
| Search (unsorted) | O(n) | Might need to check every element |
| Search (sorted) | O(log n) | Binary search |
| Insert at end | O(1) amortized | Just put it at the next slot |
| Insert at beginning/middle | O(n) | Shift all elements to the right |
| Delete at end | O(1) | Just remove the last element |
| Delete at beginning/middle | O(n) | Shift all elements to the left |
The key insight: arrays are fast for reading, slow for inserting/deleting in the middle. Every insert or delete (except at the end) forces us to shift elements.
Basic Array Operations
// Creating and accessing arrays
const nums = [10, 20, 30, 40, 50];
console.log(nums[0]); // 10 — O(1) access
console.log(nums[4]); // 50
// Insert at end — O(1) amortized
nums.push(60);
// Insert at beginning — O(n), shifts everything
nums.unshift(5);
// Delete from end — O(1)
nums.pop();
// Delete from beginning — O(n), shifts everything
nums.shift();
// Search — O(n)
const index = nums.indexOf(30); // 2
# Creating and accessing arrays (lists in Python)
nums = [10, 20, 30, 40, 50]
print(nums[0]) # 10 — O(1) access
print(nums[4]) # 50
# Insert at end — O(1) amortized
nums.append(60)
# Insert at beginning — O(n), shifts everything
nums.insert(0, 5)
# Delete from end — O(1)
nums.pop()
# Delete from beginning — O(n), shifts everything
nums.pop(0)
# Search — O(n)
index = nums.index(30) # 2
// Using ArrayList (dynamic array)
import java.util.ArrayList;
ArrayList<Integer> nums = new ArrayList<>(List.of(10, 20, 30, 40, 50));
System.out.println(nums.get(0)); // 10 — O(1) access
// Insert at end — O(1) amortized
nums.add(60);
// Insert at beginning — O(n), shifts everything
nums.add(0, 5);
// Delete from end — O(1)
nums.remove(nums.size() - 1);
// Delete from beginning — O(n), shifts everything
nums.remove(0);
// Search — O(n)
int index = nums.indexOf(30); // 2
Array Reversal
Reversing an array is one of the most common interview warm-up questions. The trick is to use two pointers — one at the start, one at the end — and swap them, moving inward.
function reverseArray(arr) {
let left = 0;
let right = arr.length - 1;
while (left < right) {
[arr[left], arr[right]] = [arr[right], arr[left]]; // swap
left++;
right--;
}
return arr;
}
console.log(reverseArray([1, 2, 3, 4, 5])); // [5, 4, 3, 2, 1]
def reverse_array(arr):
left, right = 0, len(arr) - 1
while left < right:
arr[left], arr[right] = arr[right], arr[left] # swap
left += 1
right -= 1
return arr
print(reverse_array([1, 2, 3, 4, 5])) # [5, 4, 3, 2, 1]
public static void reverseArray(int[] arr) {
int left = 0, right = arr.length - 1;
while (left < right) {
int temp = arr[left];
arr[left] = arr[right]; // swap
arr[right] = temp;
left++;
right--;
}
}
// [1, 2, 3, 4, 5] → [5, 4, 3, 2, 1]
Time: O(n), Space: O(1) — we do it in-place without extra memory.
Array Rotation
Rotating an array means shifting elements left or right by k positions. The elements that fall off one end wrap around to the other.
For example, rotating [1, 2, 3, 4, 5] left by 2 gives us [3, 4, 5, 1, 2].
The clever trick: reverse three times. Reverse the first k elements, reverse the rest, then reverse the whole array.
function rotateLeft(arr, k) {
k = k % arr.length; // handle k > length
reverse(arr, 0, k - 1); // reverse first k
reverse(arr, k, arr.length - 1); // reverse the rest
reverse(arr, 0, arr.length - 1); // reverse entire array
return arr;
}
function reverse(arr, l, r) {
while (l < r) {
[arr[l], arr[r]] = [arr[r], arr[l]];
l++; r--;
}
}
console.log(rotateLeft([1, 2, 3, 4, 5], 2)); // [3, 4, 5, 1, 2]
def rotate_left(arr, k):
k = k % len(arr) # handle k > length
def reverse(l, r):
while l < r:
arr[l], arr[r] = arr[r], arr[l]
l += 1
r -= 1
reverse(0, k - 1) # reverse first k
reverse(k, len(arr) - 1) # reverse the rest
reverse(0, len(arr) - 1) # reverse entire array
return arr
print(rotate_left([1, 2, 3, 4, 5], 2)) # [3, 4, 5, 1, 2]
public static void rotateLeft(int[] arr, int k) {
k = k % arr.length; // handle k > length
reverse(arr, 0, k - 1); // reverse first k
reverse(arr, k, arr.length - 1); // reverse the rest
reverse(arr, 0, arr.length - 1); // reverse entire array
}
private static void reverse(int[] arr, int l, int r) {
while (l < r) {
int temp = arr[l];
arr[l++] = arr[r];
arr[r--] = temp;
}
}
// [1, 2, 3, 4, 5] with k=2 → [3, 4, 5, 1, 2]
Time: O(n), Space: O(1) — three passes through the array, no extra space.
When to Use Arrays
Arrays are the go-to when we need:
- Fast access by index — O(1) lookups
- Sequential storage — elements stored in order
- Cache-friendly iteration — contiguous memory means CPU caches love arrays
They’re NOT ideal when we need:
- Frequent inserts/deletes in the middle (use a linked list)
- Dynamic key-based lookups (use a hash map)
- Fast search in unsorted data (use a hash set)
In simple language, arrays are the bread and butter of programming. They’re simple, they’re fast for reading, and they’re the building block for almost everything else. Master the two-pointer technique for array problems — it comes up everywhere.