DSA Guide
Arrays

Arrays

Two pointers, sliding windows, prefix sums and hash maps — the patterns behind most array problems

Arrays are where almost everything starts, and for good reason: they force you to think about access patterns. An array gives you O(1) random access but O(n) insertion and deletion, and nearly every technique below is a way of exploiting the first to avoid paying the second.

What an Array Actually Looks Like

An array is one continuous block of memory, divided into equal-sized slots.

nums = [2, 7, 11, 15, 3]
0
2
1
7
2
11
nums[2]
3
15
4
3
The number under each slot is its index. Indices start at 0, so the third item is nums[2].

Two things follow from "one continuous block", and between them they explain every array technique.

Why reading any index is instant

The computer knows where the block begins and how wide each slot is. So it does not search — it calculates:

address of nums[i]  =  start address  +  i × slot size

One multiplication and one addition, whatever i is. nums[999999] costs precisely what nums[0] costs. That is O(1) random access — "random" meaning any position, in any order, at the same price.

This is why indices start at 0

The index is not a counter, it is a distance from the start. The first item is 0 slots away from the beginning, the second is 1 slot away.

Once you read nums[i] as "i slots along" rather than "the i-th thing", off-by-one errors get noticeably rarer.

Why inserting is expensive

The slots must stay adjacent with no gaps — that is what makes the address arithmetic work. So making room in the middle means physically moving everything after it.

Inserting 9 at index 1
0
2
1
7
insert here
2
11
3
15
4
3
We want 9 at index 1. But index 1 is occupied, and so is every slot after it.
1 / 6
Deleting is the same in reverse: everything after the gap shifts left.

The consequence you will actually meet

Removing items from the front of a list inside a loop turns an O(n) algorithm into O(n²) — every removal quietly shifts the entire rest of the array.

Python's list.pop(0) and JavaScript's Array.shift() are exactly this trap. Use collections.deque or an index that moves instead. See stacks and queues.

The trade, in one table

OperationCostWhy
Read or write nums[i]O(1)Address arithmetic
Append at the endO(1)*Nothing to move
Insert or delete in the middleO(n)Everything after shifts
Insert or delete at the frontO(n)Everything shifts
Search an unsorted arrayO(n)Must check each slot
Search a sorted arrayO(log n)Binary search

* Amortised. The block occasionally fills up, and then the whole thing is copied to a bigger one. That copy is O(n), but it happens rarely enough that the average stays O(1).

Read that table as a set of instructions: you have a fast operation and a slow one, so build solutions out of the fast one. Every pattern below does exactly that — two pointers, sliding windows and prefix sums all read freely and never shift anything.

The Four Patterns

Almost every array problem here is one of these.

1. Hash map — turn searching into looking up

When you find yourself writing a nested loop to find "the other half" of something, a hash map usually collapses it to one pass. The cost is O(n) memory.

2. Two pointers — let a sorted (or symmetric) structure guide you

Two indices moving under a rule that provably discards possibilities. The hard part is always the proof that what you skip could not have been the answer.

3. Prefix sums — precompute so range queries become subtraction

Build cumulative totals once, and any range question becomes O(1) arithmetic.

4. Single-pass running state — carry the answer as you go

Keep one or two variables that summarise everything seen so far. Often a dynamic-programming table collapsed down to scalars.

How to Recognise Which One

The problem says…Reach for
"find a pair / has this appeared before"Hash map or set
"the array is sorted"Two pointers or binary search
"sum of a subarray / range"Prefix sums
"subarray of size k"Fixed sliding window
"longest / shortest subarray such that…"Variable sliding window
"in place, O(1) extra space"Read and write pointers
"k most frequent / largest"Counting, then bucket sort or a heap

All Problems

ProblemDifficultyPattern
Two SumEasyHash Map
Contains DuplicateEasyHash Set
Best Time to Buy and Sell StockEasyRunning Minimum
Running Sum of 1d ArrayEasyPrefix Sum
Find Pivot IndexEasyPrefix Sum
Maximum Average Subarray IEasySliding Window
Merge Sorted ArrayEasyTwo Pointers
Number of Good PairsEasyCounting
Minimum Index Sum of Two ListsEasyHash Map
Sort the PeopleEasyCustom Sort
Final Value of VariableEasySimulation
Container With Most WaterMediumTwo Pointers
Product of Array Except SelfMediumPrefix & Suffix
Group AnagramsMediumHash Map
Top K Frequent ElementsMediumBucket Sort
H-IndexMediumSorting
Remove Duplicates from Sorted Array IIMediumTwo Pointers
Trapping Rain WaterHardTwo Pointers

Where to start

If you are new to these, work through Two Sum, then Best Time to Buy and Sell Stock, then Container With Most Water. Those three cover hash maps, running state and two pointers — and everything else builds on them.

On this page