When a problem is a DP
Compute Fibonacci numbers with the textbook recursion and count the function calls. For the naive code makes 2,692,537 calls, yet there are only 31 distinct inputs, through . Almost all of the work recomputes answers the program already found. The call count is , which grows like with , so this way makes about 41 billion calls and runs for most of an hour in Python.
Two properties make a problem a candidate for dynamic programming. Overlapping subproblems: the recursion asks the same smaller question many times. Optimal substructure: the answer to the big question is built from answers to smaller ones, so solving each subproblem once and storing it is enough.
The fix costs one table. Store each the first time you compute it, and the whole thing takes evaluations: time instead of exponential.
You need both properties. Merge sort builds its answer from the answers for two halves, but the halves never share a subproblem, so a cache would never get a hit. The test in an interview is simple: write the recursion, then ask whether the same arguments come up along different branches. If they do, cache them.