Arrays & Operations

beginner arrays data-structure operations

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).

Array in Memory (contiguous)
10 20 30 40 50
[0] [1] [2] [3] [4]
Address: 0x100 → 0x104 → 0x108 → 0x10C → 0x110

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

OperationTime ComplexityWhy
Access by indexO(1)Direct address calculation
Search (unsorted)O(n)Might need to check every element
Search (sorted)O(log n)Binary search
Insert at endO(1) amortizedJust put it at the next slot
Insert at beginning/middleO(n)Shift all elements to the right
Delete at endO(1)Just remove the last element
Delete at beginning/middleO(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.