Skip to content
DSA best practices 9 min read

Common DSA Mistakes to Avoid

Most failed DSA solutions fail for a handful of repeat reasons — not exotic algorithm errors, but off-by-one bounds, overflow, mutating a collection mid-loop, and language quirks that do something other than what you’d expect. Learn this list and you’ll skip the bugs that cost everyone else hours. Each section names the trap and shows the fix.

Off-by-one errors

The classic: < vs <=, or starting at 0 vs 1. The fix is to decide whether your range is inclusive or exclusive and write every bound consistently. For binary search, the invariant “the answer is in [lo, hi]” must hold at every step:

// search [lo, hi] inclusive; loop while the range is non-empty
int lowerBound(const std::vector<int>& a, int target) {
    int lo = 0, hi = (int)a.size(); // hi is exclusive here
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;
        if (a[mid] < target) lo = mid + 1;
        else hi = mid;
    }
    return lo; // first index with a[i] >= target
}

Tip: Pick one convention — half-open [lo, hi) is the most error-resistant — and use it everywhere. Computing mid = lo + (hi - lo) / 2 also avoids the overflow trap below.

Integer overflow

In C++ and Java, int wraps silently around 2³¹. A sum of large values, a product, or (lo + hi) in binary search can overflow and produce garbage or an infinite loop. Use a 64-bit type for accumulators:

long long total = 0;            // not int
for (int x : a) total += x;     // safe for large arrays

JavaScript and Python won’t wrap like C++/Java, but JS loses precision above 2⁵³, so reach for BigInt on huge sums.

Mutating a collection while iterating

Adding to or removing from a list/map during a loop over it causes skipped elements or runtime errors. Iterate over a copy, build a new collection, or collect changes and apply them after:

#include <vector>
// Build a new vector instead of erasing during iteration.
std::vector<int> removeEvens(const std::vector<int>& a) {
    std::vector<int> out;
    for (int x : a) if (x % 2 != 0) out.push_back(x);
    return out;
}

Pitfall: In Java, removing from a list inside an enhanced for throws ConcurrentModificationException. In Python, deleting from a list you’re looping over silently skips elements. Both are fixed by building a new collection.

Wrong complexity assumptions

Two traps here. First, hidden costs: list.insert(0, x) is O(n), x in my_list is O(n), and string concatenation in a loop can be O(n²). Second, assuming average case when the grader tests the worst case — a hash map is O(1) average but O(n) under adversarial collisions, and quicksort is O(n log n) average but O(n²) on a bad pivot. Always size your idea against the constraints: at n = 10⁵, an O(n²) plan does ~10¹⁰ operations and will time out. Revisit Big-O notation when in doubt.

Language gotchas

JavaScript’s default sort is lexicographic. [10, 2, 1].sort() gives [1, 10, 2] because it sorts by string. Always pass a comparator for numbers. Python’s mutable default arguments are created once and shared across calls — a default [] accumulates between calls. Use None as the sentinel:

#include <algorithm>
#include <vector>
// C++ sort is numeric by default for ints — no gotcha here.
std::vector<int> v = {10, 2, 1};
std::sort(v.begin(), v.end()); // {1, 2, 10}

Going deeper: More language traps worth knowing — C++ iterator invalidation after push_back on a vector; Java integer caching making == work for small Integers but fail for large ones (use .equals); JavaScript’s 0.1 + 0.2 !== 0.3 floating-point surprise. When a result is bafflingly wrong, suspect the language before the algorithm.

A pre-submit checklist

  1. Bounds use one consistent convention; checked < vs <=.
  2. Accumulators are 64-bit (or BigInt) where values can be large.
  3. No collection is mutated while being iterated.
  4. The chosen complexity fits the constraints in the worst case.
  5. Sorts use explicit comparators; no mutable default arguments.

Avoiding these is most of the battle. To keep getting better, see continuing your DSA journey.

Last updated June 25, 2026
Was this helpful?