Problem 2: Longest Ascending Path Binary Tree

Method 1: backtracking version 1

// Some code
/**
 * public class TreeNode {
 *   public int key;
 *   public TreeNode left;
 *   public TreeNode right;
 *   public TreeNode(int key) {
 *     this.key = key;
 *   }
 * }
 */

/*
Clarification & Assumption
  - input: a binary tree node
  - output: the length of maximum path from any node to any leaf node
High Level
  - backtracking from top to bottom

Example: 
              5
            /.  \
          3.     2. 
      /    \.    /.  \ 
      1.   0          11
      5,
      for 3, 
                          
Middle Level
  - function, 
    - carrying the info with currentNode like a end node, to update the maximum path from definition
  - Base case, leaf node 
    - add leaf value to all paths in curResult 
    - add curResult' maximum path to result
  - curr step
    - add current node, 
  - subproblem
    - cur.left, cur.right
Recursion Tree
  - level: inherit or not inherit the path ending to curResult to left or right
  - branch: 
      left: add curMax or not curMax to left 
      right: add curMax or not curMax to right 
TC & SC: O(n), O(height)
*/
/*
maxPathEndCur: have already add cur
globalMathPathEndBeforeCur: have not add cur

*/
public class Solution {
  public int longest(TreeNode root) {
    // Write your solution here
    int[] globalMathPathEndBeforeCur = new int[]{0};
    if (root == null){
      return globalMathPathEndBeforeCur[0];
    }
    int maxPathEndCur = 1;
    backtracking(root, maxPathEndCur,globalMathPathEndBeforeCur);
    return globalMathPathEndBeforeCur[0];
  }
  private void backtracking(TreeNode cur, int maxPathEndCur, int[] globalMathPathEndBeforeCur) {
    // base case
    // return result
    if (cur == null) {
      // do not need to update since it is for before
      // globalMathPathEndBeforeCur[0] = Math.max(globalMathPathEndBeforeCur[0], maxPathEndCur);
      return;
    }
    globalMathPathEndBeforeCur[0] = Math.max(globalMathPathEndBeforeCur[0], maxPathEndCur);
    // cur
    if (cur.left != null) {
      if (cur.left.key > cur.key) {
        maxPathEndCur++;
        backtracking(cur.left, maxPathEndCur, globalMathPathEndBeforeCur);
        maxPathEndCur--;
      }
      backtracking(cur.left, 1, globalMathPathEndBeforeCur);
    }
    if (cur.right != null) {
      if (cur.right.key > cur.key) {
        maxPathEndCur++;
        backtracking(cur.right, maxPathEndCur, globalMathPathEndBeforeCur);
        maxPathEndCur--;
      }
      backtracking(cur.right, 1, globalMathPathEndBeforeCur);
    }

    // next problem
  }
}

Method 2: backtracking version 2!!!!

// Some code
public class Solution {
  public int longest(TreeNode root) {
    // Write your solution here
    int[] globalMathPathEndBeforeCur = new int[]{0};
    if (root == null){
      return globalMathPathEndBeforeCur[0];
    }
    backtracking(root, 0 , globalMathPathEndBeforeCur);
    return globalMathPathEndBeforeCur[0];
  }
  private void backtracking(TreeNode cur, int maxPathEndBeforeCur, int[] globalMathPathEndBeforeCur) {
    // base case
    // return result
    if (cur.left == null && cur.right == null) {
      maxPathEndBeforeCur++;
      globalMathPathEndBeforeCur[0] = Math.max(globalMathPathEndBeforeCur[0], maxPathEndBeforeCur);
      maxPathEndBeforeCur--;
      return;
    }
    // add cur, what happen?
    maxPathEndBeforeCur++;
    globalMathPathEndBeforeCur[0] = Math.max(globalMathPathEndBeforeCur[0], maxPathEndBeforeCur);
    // cur
    if (cur.left != null) {
      if (cur.left.key > cur.key) {
        backtracking(cur.left, maxPathEndBeforeCur, globalMathPathEndBeforeCur);
      }
      backtracking(cur.left, 0, globalMathPathEndBeforeCur);
    }
    if (cur.right != null) {
      if (cur.right.key > cur.key) {
        backtracking(cur.right, maxPathEndBeforeCur, globalMathPathEndBeforeCur);
      }
      backtracking(cur.right, 0, globalMathPathEndBeforeCur);
    }
    maxPathEndBeforeCur++;
    // next problem
  }
}

Method 2: Pure Recursion

// Some code
/*
Clarification & Assumption
  - input: a binary tree node
  - output: the length of maximum path from any node to any leaf node
High Level
  - pure recursion from bottom to up

Example: 
              5
            /.  \
          3.     2. 
      /    \.    /.  \ 
      1.   0          11
      5,
      for 3, 
                          
Middle Level
  - function, 
    - given the cur root, return the length of maximum path from any leaf to cur root
    - with globalMax
  - Base case
    - cur.left == null && cur.right == null
    - return 1;
  - subproblem
    - leftResult, rightResult
  - recursive rule
    - cur.left != null && cur.right == null
    - cur.left == null && cur.right != null
    - cur.left != null && cur.right != null
    if (cur.left.val > cur.val) curLeftInher += leftResult; update globalMax
    if (cur.right.val > cur.val) curRightInher += rightResult; update globalMax
  - return?
     return max(curleftInher, curRightInher) + 1;
      
TC & SC: O(n), O(height)
*/
/*
maxPathEndCur: have already add cur
globalMathPathEndBeforeCur: have not add cur

*/
public class Solution {
  public int longest(TreeNode root) {
    // Write your solution here
    int[] globalMax = new int[]{0};
    if (root == null) {
      return globalMax[0];
    }
    helper(root, globalMax);
    return globalMax[0];
  }
  private int helper(TreeNode cur, int[] globalMax) {
    if (cur == null) {
      return 0;
    }
    if (cur.left == null && cur.right == null) {
      globalMax[0] = Math.max(globalMax[0], 1);
      return 1;
    }
    int leftBeginMaxPath = helper(cur.left, globalMax);
    int rightBeginMaxPath = helper(cur.right, globalMax);
    int curResult = 1;
    if (cur.left != null && cur.left.key > cur.key) {
      curResult = Math.max(curResult, leftBeginMaxPath + 1);
    }
    if (cur.right != null && cur.right.key > cur.key) {
      curResult = Math.max(curResult, rightBeginMaxPath + 1);
    }
    globalMax[0] = Math.max(globalMax[0], curResult);
    return curResult;
  }
}

Last updated