Data Structure

Arrays & Strings

Arrays are the foundation of nearly every coding interview. If you can't manipulate arrays efficiently, nothing else matters.

What is it?

An array is a contiguous block of memory that stores elements of the same type, accessed by index in O(1) time. In most interview languages (Python, JavaScript, Java), arrays are dynamic — they resize automatically.

Strings are essentially arrays of characters. In Python and Java, strings are immutable — every modification creates a new string. In JavaScript, strings are also immutable but you can build with arrays and join.

The key insight: most array/string problems are really about pointer manipulation, hashing, or sorting. You rarely need the array itself to be fancy — you need clever traversal strategies.

Operations & Complexity

OperationTimeSpace
Access by indexO(1)O(1)
Search (unsorted)O(n)O(1)
Search (sorted)O(log n)O(1)
Insert at endO(1) amortizedO(1)
Insert at indexO(n)O(1)
Delete at indexO(n)O(1)
Slice / SubstringO(k)O(k)

When Interviewers Test This

Arrays and strings appear in roughly 40-50% of all coding interviews. Interviewers use them because they're universal — every candidate knows what an array is, so the problem becomes about algorithmic thinking, not data structure knowledge.

Watch for these signals:
Given an array of integers... → sliding window, two pointers, or hash map
Given a string... → usually hash map for frequency, or two pointers
In-place → two pointers or swap-based approach
Subarray → sliding window or prefix sum
Sorted array → binary search or two pointers

Implementation

Arrays — Core Patterns
1# Two-pointer pattern: remove duplicates from sorted array
2def remove_duplicates(nums: list[int]) -> int:
3 if not nums:
4 return 0
5
6 # Slow pointer tracks the position of the last unique element
7 slow = 0
8
9 for fast in range(1, len(nums)):
10 if nums[fast] != nums[slow]:
11 slow += 1
12 nums[slow] = nums[fast]
13
14 return slow + 1 # Length of unique portion
15
16
17# Prefix sum: range sum query in O(1) after O(n) preprocessing
18def build_prefix_sum(nums: list[int]) -> list[int]:
19 prefix = [0] * (len(nums) + 1)
20 for i in range(len(nums)):
21 prefix[i + 1] = prefix[i] + nums[i]
22 return prefix
23
24def range_sum(prefix: list[int], left: int, right: int) -> int:
25 return prefix[right + 1] - prefix[left]

Common Mistakes

Watch out for these

  • Off-by-one errors in loop bounds — always verify with a 1-element and 2-element array
  • Forgetting that Python slicing creates a copy (O(k) time and space), not a view
  • Mutating a string in a loop in Python/Java — use a list and join at the end
  • Not considering the empty array case — always check len(nums) == 0 first
  • Using O(n) extra space when the problem says 'in-place' — use two pointers instead

The Key Insight

Most array problems boil down to one of four techniques: two pointers, sliding window, hash map, or sorting. Before writing code, ask yourself which of these four applies. If the array is sorted, think two pointers or binary search. If you need frequency counts, think hash map. If you need a contiguous subarray, think sliding window.