thinking non-intuitively about recursion
A good example? https://leetcode.com/problems/letter-combinations-of-a-phone-number/
A top-down approach to thinking about recursion:
"Solutions" are built from the big-level tasks and integrated with the small-level tasks. This way, the solutions can be passed from the big-level tasks to the small-level tasks through the paramaters in the recursive function call. As shown in this solution to the Letter Combinations Of a Phone Number problem.
ans = []
d = {}
d["2"] = ["a","b","c"]
...
...
def backtrack(i, curstr):
if len(curstr) == len(digits):
ans.append(curstr)
return
for ch in d[digits[i]]:
backtrack(i+1, curstr + ch)
A bottom-up solution to this problem can also be implemented. Here, the solution is returned (AS AN ARRAY) from the small-level tasks and integrated into a solution from a big-level tasks.
In the Validate Binary Search Tree problem, the parameters passed (top-down) from the big-level tasks to the small-level tasks are (minValLeft & maxValRight) which is used to compute the small-level tasks. Here on the other hand, the "final solution" is a boolean which is basically the AND of all the intermediate small-level tasks/solution. Therefore, if any one small-level task/solution/validity fails, everything (the big-level solution(s)) fail(s).
def isValidBST(self, root: Optional[TreeNode]) -> bool:
def caller(node, mnleft, mxright):
if not node:
return True
if not (node.val < mxright and node.val > mnleft):
return False
return (caller(node.left, mnleft, node.val) and
caller(node.right, node.val, mxright))
return caller(root, float("-inf"), float("inf"))
Backlinks