Skip to content

Arrays, Two Pointers, Stacks & Sliding Window

Core techniques that appear in 60%+ of coding interviews


Arrays Fundamentals

5 Key Operations You Must Know

OperationTime ComplexityNotes
Access by indexO(1)arr[i] - constant time
Insert at endO(1) amortizedappend() - usually constant
Insert at indexO(n)Shifts all elements after
Delete at indexO(n)Shifts all elements after
Search (unsorted)O(n)Linear scan required

Critical Array Patterns

python
# 1. In-place reversal
def reverse(arr):
    left, right = 0, len(arr) - 1
    while left < right:
        arr[left], arr[right] = arr[right], arr[left]
        left += 1
        right -= 1

# 2. Prefix sum (for range queries)
prefix = [0]
for num in arr:
    prefix.append(prefix[-1] + num)
# Sum from i to j = prefix[j+1] - prefix[i]

# 3. Dutch National Flag (3-way partition)
def partition(arr, pivot):
    low, mid, high = 0, 0, len(arr) - 1
    while mid <= high:
        if arr[mid] < pivot:
            arr[low], arr[mid] = arr[mid], arr[low]
            low += 1
            mid += 1
        elif arr[mid] > pivot:
            arr[mid], arr[high] = arr[high], arr[mid]
            high -= 1
        else:
            mid += 1
java
// 1. In-place reversal
void reverse(int[] arr) {
    int left = 0, right = arr.length - 1;
    while (left < right) {
        int tmp = arr[left]; arr[left] = arr[right]; arr[right] = tmp;
        left++; right--;
    }
}

// 2. Prefix sum (for range queries)
int[] buildPrefix(int[] arr) {
    int[] prefix = new int[arr.length + 1];
    for (int i = 0; i < arr.length; i++) prefix[i + 1] = prefix[i] + arr[i];
    return prefix;
    // Sum from i to j = prefix[j+1] - prefix[i]
}

// 3. Dutch National Flag (3-way partition)
void partition(int[] arr, int pivot) {
    int low = 0, mid = 0, high = arr.length - 1;
    while (mid <= high) {
        if (arr[mid] < pivot) {
            int tmp = arr[low]; arr[low] = arr[mid]; arr[mid] = tmp;
            low++; mid++;
        } else if (arr[mid] > pivot) {
            int tmp = arr[mid]; arr[mid] = arr[high]; arr[high] = tmp;
            high--;
        } else { mid++; }
    }
}

Complexity: Time O(n) · Space O(1)

  • Time: Single pass through the array with three pointers
  • Space: In-place partitioning using only pointer variables

Two Pointer Pattern

Transforms O(n^2) brute force into O(n) solutions

When to Use

SignalExample Problem
Sorted array + pair/triplet searchTwo Sum II, 3Sum
Palindrome checkingValid Palindrome
In-place modificationRemove Duplicates
Merge two sorted arraysMerge Sorted Array
Container problemsContainer With Most Water

WARNING: Two pointers on unsorted arrays is a common interview mistake. Either sort first or use a hash map.

Template: Opposite Direction

python
def two_pointer_opposite(arr, target):
    """Use when searching for pairs in SORTED array"""
    left, right = 0, len(arr) - 1

    while left < right:
        current_sum = arr[left] + arr[right]

        if current_sum == target:
            return [left, right]  # Found!
        elif current_sum < target:
            left += 1   # Need larger sum
        else:
            right -= 1  # Need smaller sum

    return []  # Not found
java
int[] twoPointerOpposite(int[] arr, int target) {
    int left = 0, right = arr.length - 1;
    while (left < right) {
        int sum = arr[left] + arr[right];
        if (sum == target) return new int[]{left, right};
        else if (sum < target) left++;
        else right--;
    }
    return new int[]{};
}

Complexity: Time O(n) · Space O(1)

  • Time: Each element visited at most once as pointers converge
  • Space: Only two pointer variables used

Template: Same Direction (Fast/Slow)

python
def two_pointer_same_direction(arr):
    """Use for in-place modifications or cycle detection"""
    slow = 0  # Write pointer

    for fast in range(len(arr)):  # Read pointer
        if arr[fast] != val_to_remove:
            arr[slow] = arr[fast]
            slow += 1

    return slow  # New length
java
int twoPointerSameDirection(int[] arr, int valToRemove) {
    int slow = 0;
    for (int fast = 0; fast < arr.length; fast++) {
        if (arr[fast] != valToRemove) arr[slow++] = arr[fast];
    }
    return slow;
}

Complexity: Time O(n) · Space O(1)

  • Time: Single pass through array with fast pointer
  • Space: In-place modification using two pointer indices

Classic Problems

ProblemKey InsightOne-Liner Logic
Two Sum IISorted + targetMove pointers based on sum comparison
3SumFix one, two-pointer restSort first, skip duplicates
Container With Most WaterMax areaMove the shorter height pointer
Remove DuplicatesSlow/fast pointersSlow writes only unique values
Valid PalindromeCompare endsSkip non-alphanumeric, compare

Sliding Window Pattern

Reduces O(n^2) or O(n^3) to O(n) for subarray/substring problems

Fixed vs Variable Window

Decision Guide:

  • Fixed Window: "Find max/min sum of k consecutive elements"
  • Variable Window: "Find smallest/longest subarray with condition X"

Template: Fixed Window

python
def fixed_sliding_window(arr, k):
    """Window of exactly k elements"""
    window_sum = sum(arr[:k])
    max_sum = window_sum

    for i in range(k, len(arr)):
        window_sum += arr[i] - arr[i - k]
        max_sum = max(max_sum, window_sum)

    return max_sum
java
int fixedSlidingWindow(int[] arr, int k) {
    int windowSum = 0;
    for (int i = 0; i < k; i++) windowSum += arr[i];
    int maxSum = windowSum;
    for (int i = k; i < arr.length; i++) {
        windowSum += arr[i] - arr[i - k];
        maxSum = Math.max(maxSum, windowSum);
    }
    return maxSum;
}

Complexity: Time O(n) · Space O(1)

  • Time: Single pass after initial window setup
  • Space: Only tracking sum and max variables

Template: Variable Window

python
def variable_sliding_window(arr, target):
    """Expand right, shrink left when condition violated"""
    left = 0
    window_sum = 0
    min_length = float('inf')

    for right in range(len(arr)):
        window_sum += arr[right]

        while window_sum >= target:
            min_length = min(min_length, right - left + 1)
            window_sum -= arr[left]
            left += 1

    return min_length if min_length != float('inf') else 0
java
int variableSlidingWindow(int[] arr, int target) {
    int left = 0, windowSum = 0, minLength = Integer.MAX_VALUE;
    for (int right = 0; right < arr.length; right++) {
        windowSum += arr[right];
        while (windowSum >= target) {
            minLength = Math.min(minLength, right - left + 1);
            windowSum -= arr[left++];
        }
    }
    return minLength == Integer.MAX_VALUE ? 0 : minLength;
}

Complexity: Time O(n) · Space O(1)

  • Time: Each element added and removed from window at most once
  • Space: Only tracking window boundaries and sum

Template: Sliding Window with HashMap

python
def sliding_window_hashmap(s, k):
    """For substring problems with character frequency"""
    from collections import defaultdict

    char_count = defaultdict(int)
    left = 0
    max_length = 0

    for right in range(len(s)):
        char_count[s[right]] += 1

        while len(char_count) > k:
            char_count[s[left]] -= 1
            if char_count[s[left]] == 0:
                del char_count[s[left]]
            left += 1

        max_length = max(max_length, right - left + 1)

    return max_length
java
int slidingWindowHashmap(String s, int k) {
    Map<Character, Integer> charCount = new HashMap<>();
    int left = 0, maxLength = 0;
    for (int right = 0; right < s.length(); right++) {
        charCount.merge(s.charAt(right), 1, Integer::sum);
        while (charCount.size() > k) {
            char lc = s.charAt(left);
            charCount.merge(lc, -1, Integer::sum);
            if (charCount.get(lc) == 0) charCount.remove(lc);
            left++;
        }
        maxLength = Math.max(maxLength, right - left + 1);
    }
    return maxLength;
}

Complexity: Time O(n) · Space O(k)

  • Time: Each character added and removed from window at most once
  • Space: HashMap stores at most k distinct characters

Classic Problems

ProblemWindow TypeKey Insight
Max Sum Subarray of Size KFixedSlide and track max
Minimum Size Subarray SumVariableShrink when sum >= target
Longest Substring Without RepeatingVariableHashSet to track chars
Longest Substring with K DistinctVariableHashMap + count
Minimum Window SubstringVariableHashMap + "have" vs "need"

Stack Essentials

LIFO structure - perfect for matching pairs and "next greater" problems

When Stack is the Answer

PatternSignal WordsExample
Matching pairs"valid", "balanced", "matching"Valid Parentheses
Next greater/smaller"next", "previous", "greater", "smaller"Next Greater Element
Expression evaluation"calculate", "evaluate", "RPN"Basic Calculator
Backtracking state"undo", "history", "path"Simplify Path
Monotonic sequence"increasing/decreasing order"Daily Temperatures

Template: Matching Pairs

python
def is_valid_parentheses(s):
    """Classic bracket matching"""
    stack = []
    mapping = {')': '(', '}': '{', ']': '['}

    for char in s:
        if char in mapping:  # Closing bracket
            if not stack or stack[-1] != mapping[char]:
                return False
            stack.pop()
        else:  # Opening bracket
            stack.append(char)

    return len(stack) == 0
java
boolean isValidParentheses(String s) {
    Deque<Character> stack = new ArrayDeque<>();
    for (char c : s.toCharArray()) {
        if (c == '(' || c == '{' || c == '[') stack.push(c);
        else {
            if (stack.isEmpty()) return false;
            char top = stack.pop();
            if ((c == ')' && top != '(') || (c == '}' && top != '{')
                    || (c == ']' && top != '[')) return false;
        }
    }
    return stack.isEmpty();
}

Complexity: Time O(n) · Space O(n)

  • Time: Single pass through the string
  • Space: Stack stores at most n/2 opening brackets

Template: Monotonic Stack (Decreasing)

python
def next_greater_element(arr):
    """Find next greater element for each position"""
    n = len(arr)
    result = [-1] * n
    stack = []  # Stores indices

    for i in range(n):
        while stack and arr[stack[-1]] < arr[i]:
            idx = stack.pop()
            result[idx] = arr[i]
        stack.append(i)

    return result
java
int[] nextGreaterElement(int[] arr) {
    int[] result = new int[arr.length]; Arrays.fill(result, -1);
    Deque<Integer> stack = new ArrayDeque<>();
    for (int i = 0; i < arr.length; i++) {
        while (!stack.isEmpty() && arr[stack.peek()] < arr[i])
            result[stack.pop()] = arr[i];
        stack.push(i);
    }
    return result;
}

Complexity: Time O(n) · Space O(n)

  • Time: Each element pushed and popped at most once
  • Space: Stack and result array each store up to n elements

Template: Monotonic Stack (Increasing)

python
def daily_temperatures(temperatures):
    """Days until warmer temperature"""
    n = len(temperatures)
    result = [0] * n
    stack = []  # Stores indices of decreasing temps

    for i in range(n):
        while stack and temperatures[i] > temperatures[stack[-1]]:
            prev_idx = stack.pop()
            result[prev_idx] = i - prev_idx
        stack.append(i)

    return result
java
int[] dailyTemperatures(int[] temperatures) {
    int[] result = new int[temperatures.length];
    Deque<Integer> stack = new ArrayDeque<>();
    for (int i = 0; i < temperatures.length; i++) {
        while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
            int idx = stack.pop(); result[idx] = i - idx;
        }
        stack.push(i);
    }
    return result;
}

Complexity: Time O(n) · Space O(n)

  • Time: Each index pushed and popped at most once
  • Space: Stack stores indices; result array stores n elements

Classic Problems

ProblemStack TypeKey Insight
Valid ParenthesesRegularPush open, pop on close
Daily TemperaturesMonotonic decreasingPop when temp rises
Largest Rectangle in HistogramMonotonic increasingPop when height decreases
Trapping Rain WaterMonotonic or two-pointerStack tracks "pits"
Evaluate RPNRegularPop operands, push result

Quick Problem Matrix

ProblemPatternKey Insight
Two Sum IITwo PointersSorted array, move based on sum
3SumTwo PointersFix one, two-pointer for rest
Container With Most WaterTwo PointersMove shorter height pointer
Remove Duplicates from Sorted ArrayTwo PointersSlow/fast pointer in-place
Maximum Subarray Sum (size k)Fixed WindowSlide, add right, remove left
Minimum Size Subarray SumVariable WindowExpand right, shrink left
Longest Substring Without RepeatingVariable Window + HashSetShrink on duplicate
Valid ParenthesesStackPush open, match on close
Daily TemperaturesMonotonic StackPop when find warmer day
Largest Rectangle in HistogramMonotonic StackPop on smaller height

Interview Applications

How These Patterns Appear in Interviews

  1. Two Pointers in Interviews

    • Often combined with binary search for optimization
    • "Find pairs/triplets with specific sum" is a classic Google phone screen question
    • Watch for: sorted array inputs signal two-pointer approach
  2. Sliding Window in Interviews

    • Google loves substring problems with character frequency conditions
    • Real-world connection: network packet analysis, log processing
    • Common variation: "Find minimum window containing all characters from target"
  3. Stack in Interviews

    • Expression parsing (think Google Sheets formulas)
    • Nested structure validation (HTML/XML parsing)
    • Histogram problems are Google favorites (Largest Rectangle)

Google-Style Problem Combinations

CombinationExample
Two Pointers + Binary Search"Find pair with sum closest to target"
Sliding Window + HashMap"Longest substring with at most K distinct characters"
Stack + Arrays"Trapping Rain Water" (can solve with stack or two pointers)
Monotonic Stack + DP"Sum of Subarray Minimums"

Interview Tips from Top Sources

  1. Start with brute force - Explain why O(n^2) or O(n^3) is inefficient
  2. Identify the pattern signal - Sorted array? Use two pointers. Subarray/substring? Try sliding window. Matching or ordering? Consider stack.
  3. Handle edge cases explicitly:
    • Empty array
    • Single element
    • All same elements
    • Window size larger than array

Quick Reference Card

PATTERN SELECTION FLOWCHART:

Is input sorted or needs pairs/triplets?
    YES -> Two Pointers (opposite direction)

Need to modify array in-place?
    YES -> Two Pointers (same direction)

Looking for contiguous subarray/substring with constraint?
    YES -> Sliding Window
    - Known size k? -> Fixed Window
    - Find min/max length? -> Variable Window

Need matching pairs or "next greater/smaller"?
    YES -> Stack (possibly monotonic)

Need to evaluate expressions or track history?
    YES -> Stack

Sources