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 ​