Reviews code for algorithmic complexity issues: nested loops, N+1 queries, exponential recursion, and optimization suggestions across multiple languages.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pproenca-dot-skills-1:algorithmic-complexity-reviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Find, classify, and fix algorithmic complexity (Big-O) problems in code — language-agnostic. The 39 rules across 8 categories cover the patterns responsible for the vast majority of accidental quadratic, exponential, and N+1 blowups in production code: nested iteration, loop-invariant I/O, data-structure mismatch, recursion explosions, redundant computation, collection-building anti-patterns, s...
Find, classify, and fix algorithmic complexity (Big-O) problems in code — language-agnostic. The 39 rules across 8 categories cover the patterns responsible for the vast majority of accidental quadratic, exponential, and N+1 blowups in production code: nested iteration, loop-invariant I/O, data-structure mismatch, recursion explosions, redundant computation, collection-building anti-patterns, search/sort selection, and space traps.
Use this skill when:
.includes/.find/x in list inside iteration, ORM access in a loop, recursion without memoization, string/array building via += or spread, file/database I/O inside iterationThe skill is structured for a three-step workflow on any code under review:
Look for these structural signals first (highest hit rate):
| Signal | Likely Category | First Rule to Check |
|---|---|---|
Two nested for loops | nested- | nested-explicit-quadratic-loops |
.includes / .find / x in list inside a loop | nested- | nested-includes-in-loop |
ORM access inside a loop (for o in orders: o.customer.x) | io- | io-n-plus-one-query |
await fetch in for-of | io- | io-sequential-await-in-loop |
array.find to "join" two arrays | ds- | ds-hashmap-for-keyed-access |
| Recursive function with overlapping arguments | rec- | rec-memoize-overlapping-subproblems |
s = s + part or [...acc, x] in a loop | build- | build-avoid-quadratic-string-concat, build-avoid-spread-in-reducer |
sorted(...) called inside a loop | search- | search-sort-once-outside-loop |
readlines() / loading whole files | space- | space-stream-dont-load |
Compute complexity from the code structure:
| Structure | Complexity |
|---|---|
| Single loop over n items, O(1) body | O(n) |
| Two nested loops over n / m items | O(n*m) |
Loop calling an O(n) operation (.includes, .find, x in list) | O(n*m), often misread as O(n) |
Recursive f(n) = f(n-1) + f(n-2) without memoization | O(2ⁿ) |
Recursive f(n) = 2*f(n/2) + O(n) | O(n log n) |
Recursive f(n) = 2*f(n/2) + O(1) | O(n) (full tree traversal) |
Recursive f(n) = f(n/2) + O(1) | O(log n) |
s = s + part in a loop | O(n²) (string immutability) |
[...acc, x] in a reduce | O(n²) (copy-on-spread) |
| Query/RPC inside loop over n items | O(n) round trips |
When in doubt, ask: "As input doubles, does runtime roughly double (linear), quadruple (quadratic), or do something worse (exponential)?" That's the practical complexity class.
Each reference file in references/ is a {category}-{slug}.md containing:
The minimal diff philosophy is intentional: the goal is for the agent to see exactly how few lines need to change to flip the complexity class.
| # | Category | Prefix | Impact | Rules |
|---|---|---|---|---|
| 1 | Nested Iteration Patterns | nested- | CRITICAL | 6 |
| 2 | Loop-Invariant I/O and N+1 | io- | CRITICAL | 5 |
| 3 | Data Structure Mismatch | ds- | HIGH | 6 |
| 4 | Recursion Complexity | rec- | HIGH | 5 |
| 5 | Redundant Computation | compute- | MEDIUM-HIGH | 5 |
| 6 | Collection Building | build- | MEDIUM | 4 |
| 7 | Search & Sort Selection | search- | MEDIUM | 4 |
| 8 | Space Complexity Traps | space- | LOW-MEDIUM | 4 |
See references/_sections.md for the full ordering rationale.
nested-explicit-quadratic-loops — Replace pairwise loops with hash-based single passesnested-includes-in-loop — Avoid .includes() / .indexOf() inside a loopnested-find-in-loop — Pre-index lookups instead of .find() per iterationnested-cartesian-comparison — Group by key instead of cartesian comparisonnested-set-operations-on-arrays — Use sets for intersection, union, differencenested-substring-search-in-loop — Tokenize once instead of re-scanning per patternio-n-plus-one-query — Eliminate N+1 queries by fetching related data in one round tripio-sequential-await-in-loop — Run independent async operations in parallelio-batch-instead-of-per-item — Use batch endpoints instead of per-item callsio-file-read-in-loop — Read or stat files outside tight loopsio-missing-eager-load — Eager-load ORM relations you will accessds-hashmap-for-keyed-access — Store records keyed in a hashmap, not as parallel arraysds-heap-for-top-k — Use a heap for top-k, not full sort + sliceds-deque-for-front-operations — Use a deque for front insertions and removalsds-counter-for-histograms — Use Counter / multiset for frequency countingds-sorted-structure-for-range-queries — Use a sorted structure for range queriesds-trie-for-prefix-search — Use a trie for prefix searchrec-memoize-overlapping-subproblems — Memoize recursion with overlapping subproblemsrec-tabulate-bottom-up — Tabulate bottom-up to eliminate recursion overheadrec-iterative-for-deep-recursion — Use an explicit stack instead of deep recursionrec-prune-with-bounds — Prune recursive search with bounds and constraintsrec-share-memo-across-top-level-calls — Share memoization across top-level callscompute-hoist-loop-invariants — Hoist loop-invariant computation outside the loopcompute-precompile-regex — Pre-compile regex patternscompute-cache-expensive-pure-results — Cache expensive pure-function resultscompute-cache-property-lookup — Cache repeated property lookups in hot loopscompute-defer-or-short-circuit — Defer or short-circuit work you might not needbuild-avoid-quadratic-string-concat — Build strings with joins or builders, not repeated concatenationbuild-avoid-spread-in-reducer — Push to a mutable accumulator instead of spreadingbuild-avoid-immutable-object-spread — Use a plain object build phase, then freezebuild-presize-when-length-known — Pre-size collections when the length is knownsearch-binary-search-on-sorted — Use binary search on sorted datasearch-sort-once-outside-loop — Sort once outside the loop, not on every iterationsearch-quickselect-not-full-sort — Use quickselect for the k-th element, not full sortsearch-build-index-once-amortize — Build the index once when queries dominatespace-stream-dont-load — Stream large inputs instead of loading them wholespace-generators-over-intermediate-lists — Pipe through generators instead of materializing intermediate listsspace-shallow-not-deep-copy — Use shallow copies (or no copy) instead of deep clonesspace-release-retained-references — Release references that prevent garbage collectionreferences/_sections.md for category ordering rationale, and assets/templates/_template.md when adding new rules.| File | Description |
|---|---|
| references/_sections.md | Category definitions, impact levels, and ordering rationale |
| assets/templates/_template.md | Template for adding new rules |
| metadata.json | Discipline, type, and source references |
bug-review — Multi-pass PR bug review (this skill is a focused complement for performance issues specifically)npx claudepluginhub pproenca/dot-skillsReduces Big-O of existing code using a one-transformation-at-a-time playbook with verify-revert-stop. Targets nested loops, N+1 queries, redundant allocations, and serial await-in-for patterns.
Scans codebases for algorithmic complexity hotspots (nested loops, N+1 queries, O(n^2) patterns) and produces a structured report with ranked findings and safe optimization suggestions.
Detects time and space complexity hotspots via AST scan. Use when code feels slow, before performance-sensitive merges, or to find O(n²) regressions.