smithery.ai

algorithm-pattern-reference

Quick reference guide for common algorithm patterns including two pointers, sliding window, binary search, DFS, BFS, dynamic programming, greedy algorithms, and more. Use when identifying patterns, learning templates, or looking up specific algorithmic techniques.

First seen Apr 2, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 16,126 B
  • docs SUMMARY.md 299 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Algorithm Pattern Reference

Quick reference for common coding patterns and their templates.

Array & String Patterns

Two Pointers

When to use:

  • Sorted arrays
  • Finding pairs or triplets
  • Palindrome checks
  • Removing duplicates
  • Partitioning arrays

Template (opposite ends):

def two_pointers_opposite(arr):
    left, right = 0, len(arr) - 1

    while left < right:
        # Process current pair
        if condition(arr[left], arr[right]):
            # Found solution
            return result
        elif some_check:
            left += 1
        else:
            right -= 1

    return default

Template (same direction):

def two_pointers_same(arr):
    slow = 0

    for fast in range(len(arr)):
        if condition(arr[fast]):
            arr[slow] = arr[fast]
            slow += 1

    return slow  # or arr[:slow]

Examples:

  • Two Sum II (sorted array)
  • Container With Most Water
  • Remove Duplicates from Sorted Array
  • Valid Palindrome

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


Sliding Window

When to use:

  • Contiguous subarray/substring problems
  • Maximum/minimum of subarrays of size K
  • Longest substring with constraint
  • Finding all anagrams

Template (fixed size):

def sliding_window_fixed(arr, k):
    window_sum = sum(arr[:k])
    max_sum = window_sum

    for i in range(k, len(arr)):
        # Slide window: remove left, add right
        window_sum = window_sum - arr[i - k] + arr[i]
        max_sum = max(max_sum, window_sum)

    return max_sum

Template (variable size):

def sliding_window_variable(arr):
    left = 0
    result = 0
    window = {}  # or set, or counter

    for right in range(len(arr)):
        # Expand window
        window[arr[right]] = window.get(arr[right], 0) + 1

        # Contract window while invalid
        while not is_valid(window):
            window[arr[left]] -= 1
            if window[arr[left]] == 0:
                del window[arr[left]]
            left += 1

        # Update result
        result = max(result, right - left + 1)

    return result

Examples:

  • Maximum Sum Subarray of Size K
  • Longest Substring Without Repeating Characters
  • Minimum Window Substring
  • Find All Anagrams in a String

Time: O(n) Space: O(k) where k is window size or alphabet size


Prefix Sum

When to use:

  • Range sum queries
  • Subarray sum equals K
  • Continuous subarrays

Template:

def prefix_sum(arr):
    prefix = [0]

    for num in arr:
        prefix.append(prefix[-1] + num)

    # Range sum from i to j (inclusive)
    # sum = prefix[j + 1] - prefix[i]

    return prefix

# With hash map for subarray sum
def subarray_sum(arr, target):
    prefix_sum = 0
    sum_count = {0: 1}  # sum -> frequency
    result = 0

    for num in arr:
        prefix_sum += num

        # Check if (prefix_sum - target) exists
        if prefix_sum - target in sum_count:
            result += sum_count[prefix_sum - target]

        sum_count[prefix_sum] = sum_count.get(prefix_sum, 0) + 1

    return result

Examples:

  • Range Sum Query
  • Subarray Sum Equals K
  • Contiguous Array

Time: O(n) for building, O(1) for query Space: O(n)


Search Patterns

Binary Search

When to use:

  • Sorted arrays
  • Finding boundaries
  • Minimizing/maximizing with condition
  • Search in rotated sorted array

Template (find exact):

def binary_search(arr, target):
    left, right = 0, len(arr) - 1

    while left <= right:
        mid = left + (right - left) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1  # not found

Template (find boundary):

def find_first(arr, target):
    left, right = 0, len(arr) - 1
    result = -1

    while left <= right:
        mid = left + (right - left) // 2

        if arr[mid] == target:
            result = mid
            right = mid - 1  # keep searching left
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return result

def find_last(arr, target):
    left, right = 0, len(arr) - 1
    result = -1

    while left <= right:
        mid = left + (right - left) // 2

        if arr[mid] == target:
            result = mid
            left = mid + 1  # keep searching right
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return result

Template (minimize/maximize):

def minimize_max(arr, condition):
    left, right = min(arr), max(arr)

    while left < right:
        mid = left + (right - left) // 2

        if is_feasible(arr, mid):
            right = mid  # try smaller
        else:
            left = mid + 1

    return left

Examples:

  • Binary Search
  • Find First and Last Position
  • Search in Rotated Sorted Array
  • Capacity To Ship Packages Within D Days

Time: O(log n) Space: O(1)


Tree Patterns

DFS (Depth-First Search)

When to use:

  • Tree traversal (preorder, inorder, postorder)
  • Path finding
  • Tree depth/height
  • Validate BST

Template (recursive):

def dfs_recursive(root):
    if not root:
        return base_case

    # Preorder: process current, then children
    result = process(root.val)
    left = dfs_recursive(root.left)
    right = dfs_recursive(root.right)

    # Postorder: process children, then current
    return combine(result, left, right)

# With helper for global state
def dfs_with_state(root):
    result = []

    def dfs(node, state):
        if not node:
            return

        # Update state
        state.append(node.val)

        # Leaf node check
        if not node.left and not node.right:
            result.append(state[:])

        dfs(node.left, state)
        dfs(node.right, state)

        # Backtrack
        state.pop()

    dfs(root, [])
    return result

Template (iterative):

def dfs_iterative(root):
    if not root:
        return []

    stack = [root]
    result = []

    while stack:
        node = stack.pop()
        result.append(node.val)

        # Push right first so left is processed first
        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)

    return result

Examples:

  • Binary Tree Paths
  • Maximum Depth of Binary Tree
  • Path Sum
  • Validate Binary Search Tree

Time: O(n) Space: O(h) where h is height (recursion stack)


BFS (Breadth-First Search)

When to use:

  • Level-order traversal
  • Shortest path in unweighted graph/tree
  • Finding nodes at specific level
  • Minimum depth

Template:

from collections import deque

def bfs(root):
    if not root:
        return []

    queue = deque([root])
    result = []

    while queue:
        level_size = len(queue)
        level = []

        for _ in range(level_size):
            node = queue.popleft()
            level.append(node.val)

            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)

        result.append(level)

    return result

Examples:

  • Binary Tree Level Order Traversal
  • Minimum Depth of Binary Tree
  • Zigzag Level Order Traversal
  • Binary Tree Right Side View

Time: O(n) Space: O(w) where w is maximum width


Graph Patterns

Graph DFS

When to use:

  • Connected components
  • Cycle detection
  • Topological sort
  • Path finding

Template:

def graph_dfs(graph):
    visited = set()

    def dfs(node):
        if node in visited:
            return

        visited.add(node)

        for neighbor in graph[node]:
            dfs(neighbor)

    # Visit all components
    for node in graph:
        if node not in visited:
            dfs(node)

    return visited

Examples:

  • Number of Islands
  • Clone Graph
  • Course Schedule
  • All Paths From Source to Target

Time: O(V + E) Space: O(V)


Graph BFS

When to use:

  • Shortest path in unweighted graph
  • Level-by-level exploration
  • Finding distance

Template:

from collections import deque

def graph_bfs(graph, start):
    queue = deque([start])
    visited = {start}
    distance = {start: 0}

    while queue:
        node = queue.popleft()

        for neighbor in graph[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)
                distance[neighbor] = distance[node] + 1

    return distance

Examples:

  • Word Ladder
  • Shortest Path in Binary Matrix
  • Rotting Oranges

Time: O(V + E) Space: O(V)


Union-Find (Disjoint Set)

When to use:

  • Connected components in dynamic graph
  • Cycle detection in undirected graph
  • Kruskal's algorithm

Template:

class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])  # path compression
        return self.parent[x]

    def union(self, x, y):
        root_x, root_y = self.find(x), self.find(y)

        if root_x == root_y:
            return False  # already connected

        # Union by rank
        if self.rank[root_x] < self.rank[root_y]:
            self.parent[root_x] = root_y
        elif self.rank[root_x] > self.rank[root_y]:
            self.parent[root_y] = root_x
        else:
            self.parent[root_y] = root_x
            self.rank[root_x] += 1

        return True

    def connected(self, x, y):
        return self.find(x) == self.find(y)

Examples:

  • Number of Connected Components
  • Redundant Connection
  • Accounts Merge

Time: O(α(n)) amortized per operation (nearly constant) Space: O(n)


Dynamic Programming Patterns

1D DP

When to use:

  • Fibonacci-like problems
  • House robber variants
  • Climbing stairs

Template:

def dp_1d(arr):
    n = len(arr)
    if n == 0:
        return 0

    dp = [0] * n
    dp[0] = base_case

    for i in range(1, n):
        dp[i] = max(
            dp[i-1] + arr[i],  # include current
            dp[i-1]             # exclude current
        )

    return dp[n-1]

# Space optimized
def dp_1d_optimized(arr):
    prev, curr = 0, 0

    for num in arr:
        prev, curr = curr, max(curr, prev + num)

    return curr

Examples:

  • Climbing Stairs
  • House Robber
  • Decode Ways

Time: O(n) Space: O(n) or O(1) optimized


2D DP

When to use:

  • Grid problems
  • String matching
  • Knapsack variants

Template:

def dp_2d(grid):
    m, n = len(grid), len(grid[0])
    dp = [[0] * n for _ in range(m)]

    # Initialize base cases
    dp[0][0] = grid[0][0]

    # Fill first row and column
    for i in range(1, m):
        dp[i][0] = dp[i-1][0] + grid[i][0]
    for j in range(1, n):
        dp[0][j] = dp[0][j-1] + grid[0][j]

    # Fill rest of table
    for i in range(1, m):
        for j in range(1, n):
            dp[i][j] = grid[i][j] + min(
                dp[i-1][j],   # from top
                dp[i][j-1]    # from left
            )

    return dp[m-1][n-1]

Examples:

  • Unique Paths
  • Minimum Path Sum
  • Edit Distance
  • Longest Common Subsequence

Time: O(m n) Space: O(m n) or O(n) optimized


Knapsack Pattern

When to use:

  • Subset sum
  • Target sum
  • Partition problems

Template (0/1 Knapsack):

def knapsack(weights, values, capacity):
    n = len(weights)
    dp = [[0] * (capacity + 1) for _ in range(n + 1)]

    for i in range(1, n + 1):
        for w in range(1, capacity + 1):
            if weights[i-1] <= w:
                dp[i][w] = max(
                    values[i-1] + dp[i-1][w - weights[i-1]],  # include
                    dp[i-1][w]                                  # exclude
                )
            else:
                dp[i][w] = dp[i-1][w]

    return dp[n][capacity]

Examples:

  • Partition Equal Subset Sum
  • Target Sum
  • Coin Change

Time: O(n capacity) Space: O(n capacity)


Other Important Patterns

Backtracking

When to use:

  • Generate all permutations/combinations
  • Subsets
  • N-Queens
  • Sudoku solver

Template:

def backtrack(nums):
    result = []

    def helper(path, remaining):
        # Base case: found valid solution
        if is_complete(path):
            result.append(path[:])
            return

        # Try all possibilities
        for i, num in enumerate(remaining):
            # Make choice
            path.append(num)

            # Recurse with updated state
            helper(path, remaining[:i] + remaining[i+1:])

            # Undo choice (backtrack)
            path.pop()

    helper([], nums)
    return result

Examples:

  • Permutations
  • Subsets
  • Combination Sum
  • Generate Parentheses

Time: Varies (often O(2^n) or O(n!)) Space: O(n) recursion depth


Monotonic Stack

When to use:

  • Next greater/smaller element
  • Histogram problems
  • Stock span

Template:

def monotonic_stack(arr):
    stack = []  # stores indices
    result = [-1] * len(arr)

    for i in range(len(arr)):
        # Maintain monotonic property
        while stack and arr[stack[-1]] < arr[i]:
            idx = stack.pop()
            result[idx] = arr[i]  # arr[i] is next greater

        stack.append(i)

    return result

Examples:

  • Next Greater Element
  • Daily Temperatures
  • Largest Rectangle in Histogram

Time: O(n) Space: O(n)


Fast & Slow Pointers

When to use:

  • Cycle detection in linked list
  • Finding middle of linked list
  • Happy number

Template:

def has_cycle(head):
    slow = fast = head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

        if slow == fast:
            return True

    return False

def find_cycle_start(head):
    slow = fast = head

    # Find meeting point
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            break

    if not fast or not fast.next:
        return None

    # Find cycle start
    slow = head
    while slow != fast:
        slow = slow.next
        fast = fast.next

    return slow

Examples:

  • Linked List Cycle
  • Find Duplicate Number
  • Happy Number

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


Greedy

When to use:

  • Locally optimal choice leads to global optimum
  • Interval scheduling
  • Jump game

Template:

def greedy(arr):
    # Sort if needed
    arr.sort(key=lambda x: some_criteria)

    result = 0
    current_state = initial_state

    for item in arr:
        if can_take(item, current_state):
            result += 1
            current_state = update(current_state, item)

    return result

Examples:

  • Jump Game
  • Meeting Rooms II
  • Gas Station

Time: Varies, often O(n log n) due to sorting Space: O(1) typically


Quick Pattern Identification

Keywords Pattern
Sorted array Binary search, two pointers
Substring/subarray Sliding window
All pairs Nested loops or hash map
Tree traversal DFS or BFS
Graph connectivity Union-find or DFS
Shortest path BFS (unweighted), Dijkstra (weighted)
Optimal/max/min subproblem Dynamic programming
Generate all Backtracking
Next greater/smaller Monotonic stack
Top K Heap
Cycle detection Fast & slow pointers
Local optimal → global Greedy

Use this reference to quickly identify which pattern applies to your problem!