DEV Community

What Word Break Leetcode Problem Taught Me About Debugging Order

I recently worked through the classic Word Break problem in an interview. My approach was solid from the start - recursion with memoization, a breakable helper that tests every prefix and recurses on the rest. The logic was right. What slowed me down was everything around the logic.

Here's the solution I landed on:

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> dict(wordDict.begin(), wordDict.end());
        unordered_map<size_t, bool> memo;
        return breakable(s, dict, memo, 0);
        // missed: breakable was a free function defined below -> "not declared in this scope"
    }
private:
    // missed: had int here, compared against s.length() (size_t) -> sign-compare warnings
    bool breakable(const string& s, const unordered_set<string>& dict,
                   unordered_map<size_t, bool>& memo, size_t starting) {
        if (starting == s.length()) return true;
        if (memo.count(starting)) return memo[starting];
        for (size_t e = starting + 1; e <= s.length(); e++) {
            string word = s.substr(starting, e - starting);
            // missed: shadowed an outer `word`, and had substr(starting, e) instead of e - starting
            if (dict.count(word) && breakable(s, dict, memo, e)) {
                memo[starting] = true;
                // missed: wrote == instead of =, so success was never cached
                return true;
            }
        }
        memo[starting] = false;
        // missed: this line, so failures were never cached and memoization broke down
        return false;
    }
};

The real lesson

Most of what tripped me up was syntax and scope - a function declared in the wrong place, signed/unsigned mismatches, a shadowed variable, == where I meant =. None of these were about the algorithm. But because I spent my time chasing them, I had less room to focus on the one thing that actually matters in this problem: the logical correctness of the memoization.

The takeaway I'm keeping

Get the syntax and scoping clean early, so the debugging budget goes toward logic, not typos. That's the difference between a working solution and a working solution you can reason about under pressure.

Comments

No comments yet. Start the discussion.