Search code examples
algorithmrecursionconditional-statementsbinary-treedepth

Are recursive calls made in a conditional statement?


I'm trying to walkthrough the following recursive code to find the depth of a binary tree, but do not know if recursive calls in conditionals are called:

var maxDepth = function (root) {
  return maxDepthHandler(root, 1);
};

var maxDepthHandler = function (root, depth) {
  if (!root) {
    return 0;
  }
  if (!root.right && !root.left) {
    return depth;
  }
  if (root.right && root.left) {
    // are these recursive functions called when checking the condition?
    if (
      maxDepthHandler(root.right, depth + 1) >
      maxDepthHandler(root.left, depth + 1)
    ) {
      return maxDepthHandler(root.right, depth + 1);
    } else {
      // for my follow up question: is this the first recursive call?
      return maxDepthHandler(root.left, depth + 1);
    }
  } else if (root.right !== null) {
    return maxDepthHandler(root.right, depth + 1);
  } else {
    return maxDepthHandler(root.left, depth + 1);
  }
};

Given the following graph:

        13
       /  \
      8    37
     / \   / \
    6  11 24 42

If recursive calls aren't called in conditionals, does that mean running maxDepth(13) will result in maxDepthHandler(root.left, depth + 1); to be the first recursive call? The reason I think this is because at the first call, if recursive calls in conditionals are not called, the conditional cannot be calculated, therefore the else statement is run.


Solution

  • In your specific case, they are all called. That implies that you should probably capture their values to avoid repeated effort:

    let right = maxDepthHandler(root.right, depth + 1);
    let left = maxDepthHandler(root.left, depth + 1);
    if (right > left) {
      return right;
    } else {
      return left;
    }
    

    or:

    let right = maxDepthHandler(root.right, depth + 1);
    let left = maxDepthHandler(root.left, depth + 1);
    return right > left ? right : left;
    

    or:

    let right = maxDepthHandler(root.right, depth + 1);
    let left = maxDepthHandler(root.left, depth + 1);
    return Math.max(left, right);
    

    or:

    return Math.max(maxDepthHandler(root.left, depth + 1), maxDepthHandler(root.right, depth + 1));
    

    As a side note, because you are handling the null root case by returning 0, I think most of your other conditions on root.right and root.left being null will be handled automatically if your entire function becomes:

      if (!root) {
        return 0;
      }
      return Math.max(maxDepthHandler(root.left, depth + 1), maxDepthHandler(root.right, depth + 1));
    

    However there are cases where function calls in conditionals are not called. For example:

    if(foo(1) || foo(2)) {
    ...
    }
    if(foo(3) && foo(4)) {
    ...
    }
    

    In this example, if foo(1) returns true, the || operator will short-circuit and not bother calling foo(2). If foo(3) returns false, the && operator will short-circuit so foo(4) won't be called.