data structures algorithms35 min

Arrays Deep Dive

Array operations, two-pointer techniques, and sliding window patterns

0/9Not Started

Why This Matters

You already know how to use arrays -- push, pop, map, filter. But in technical interviews and production code, the basic operations are not enough. You need patterns -- reusable strategies for solving entire categories of problems efficiently.

The two-pointer technique and sliding window pattern are two of the most powerful tools in algorithm design. They turn naive O(n^2) brute-force solutions into elegant O(n) algorithms. Once you learn these patterns, you will recognize them everywhere: in search algorithms, string processing, data streaming, and interview questions.

Understanding how dynamic arrays work under the hood also helps you make better performance decisions -- knowing when operations are O(1) versus O(n) can prevent subtle production bottlenecks.

Define Terms

Visual Model

sorted
0
1
1
3
2
5
3
7
4
9
5
11
6
14

The full process at a glance. Click Start tour to walk through each step.

Two pointers move inward from both ends, narrowing the search space with each step.

Code Example

Code
// TWO-POINTER: Find pair with target sum in sorted array
function twoSum(sorted, target) {
  let left = 0;
  let right = sorted.length - 1;
  while (left < right) {
    const sum = sorted[left] + sorted[right];
    if (sum === target) return [sorted[left], sorted[right]];
    if (sum < target) left++;    // need larger sum
    else right--;                // need smaller sum
  }
  return null;
}
console.log(twoSum([1, 3, 5, 7, 9, 11, 14], 14)); // [3, 11]

// SLIDING WINDOW: Maximum sum of k consecutive elements
function maxSubarraySum(arr, k) {
  if (arr.length < k) return null;
  // Calculate sum of first window
  let windowSum = 0;
  for (let i = 0; i < k; i++) {
    windowSum += arr[i];
  }
  let maxSum = windowSum;
  // Slide the window: add next, remove first
  for (let i = k; i < arr.length; i++) {
    windowSum += arr[i] - arr[i - k];
    maxSum = Math.max(maxSum, windowSum);
  }
  return maxSum;
}
console.log(maxSubarraySum([2, 1, 5, 1, 3, 2], 3)); // 9 (5+1+3)

// DYNAMIC ARRAY: How push works under the hood
// Arrays double capacity when full
const arr = [];
for (let i = 0; i < 8; i++) {
  arr.push(i);  // Usually O(1), occasionally O(n) when resizing
}
console.log(arr); // [0, 1, 2, 3, 4, 5, 6, 7]

// PREFIX SUM: precompute sums for O(1) range queries
function buildPrefixSum(arr) {
  const prefix = [0];
  for (let i = 0; i < arr.length; i++) {
    prefix.push(prefix[i] + arr[i]);
  }
  return prefix;
}
function rangeSum(prefix, left, right) {
  return prefix[right + 1] - prefix[left];
}
const prefix = buildPrefixSum([3, 1, 4, 1, 5]);
console.log(rangeSum(prefix, 1, 3)); // 6 (1+4+1)

Interactive Experiment

Try these exercises:

  • Modify the two-pointer twoSum function to return the indices instead of the values.
  • Use the sliding window pattern to find the smallest subarray whose sum is greater than or equal to a given target.
  • Write a function that rotates an array by k positions to the right using O(1) extra space. Hint: reverse three times.
  • Build a prefix sum array and use it to answer 5 different range sum queries. Compare this to computing each sum from scratch with a loop.

Quick Quiz

Coding Challenge

Two-Pointer Pair Sum

Write a function `pairSum` that takes a SORTED array of integers and a target sum. Return the indices (as a two-element array) of the two numbers that add up to the target. Use the two-pointer technique for O(n) time and O(1) space. If no pair exists, return [-1, -1].

Loading editor...

Real-World Usage

These array patterns appear throughout production software:

  • Merge operations: Git's merge algorithm uses a two-pointer approach to walk through two sorted commit histories simultaneously.
  • Network monitoring: Sliding window protocols (like TCP) track which packets have been sent and acknowledged using a window that slides forward over time.
  • Data streaming: Analytics systems compute running averages, max values, and anomaly detection over sliding windows of time-series data.
  • Search results: Merging results from multiple sorted indexes (like Elasticsearch shards) uses multi-pointer merging.
  • Memory allocators: Dynamic arrays and amortized resizing are how JavaScript arrays, Python lists, and Java ArrayLists work internally.

Connections