package com.interview.leetcode.tree;
import com.interview.basics.model.tree.BinaryTree;
import com.interview.basics.model.tree.BinaryTreeNode;
import com.interview.leetcode.utils.TreeNode;
import java.util.ArrayList;
import java.util.List;
/**
* Created_By: stefanie
* Date: 14-11-22
* Time: 下午8:38
*/
public class TreePath {
/**
* You are given a binary tree in which each node contains a value. Design an algorithm
to print all paths which sum up to that value. Note that it can be any path in the tree
- it does not have to start at the root.
*/
static class PathSum {
public static void findSum(BinaryTree<Integer> tree, int sum) {
int height = getHeight(tree.getRoot());
int[] buffer = new int[height];
findSum(tree.getRoot(), sum, buffer, 0);
}
private static void findSum(BinaryTreeNode<Integer> node, int sum, int[] buffer, int level) {
if (node == null) return;
buffer[level] = node.value;
int tmp = 0;
for (int i = level; i >= 0; i--) {
tmp += buffer[i];
if (tmp == sum) printPath(buffer, i, level);
}
findSum(node.left, sum, buffer, level + 1);
findSum(node.right, sum, buffer, level + 1);
buffer[level] = 0;
}
private static void printPath(int[] buffer, int start, int end) {
for (int i = start; i <= end; i++) System.out.print(buffer[i] + " ");
System.out.println();
}
private static int getHeight(BinaryTreeNode<Integer> node) {
if (node == null) return 0;
int left = getHeight(node.left);
int right = getHeight(node.right);
return Math.max(left, right) + 1;
}
}
/** Given a binary tree, find the maximum path sum. The path may start and end at any node in the tree.
* For example: Given the below binary tree,
* 1
* / \
* 2 3
* Return 6.
*
* Solutions:
* The max path should have following 4 cases:
* i. max(left subtree) + node
* ii. max(right subtree) + node
* iii. max(left subtree) + max(right subtree) + node
* iv. the node itself (!!!!important)
* The path of root is depends on both left and right subtree, should use post-order traverse.
* It's a standard divide and conquer sample for Tree, in post-order traverse.
*
* Tricks:
* 1. Define a simplest and clear calculation method for the variable you interested (max path), may have several different cases.
* 2. For tree problem, find a suitable traverse: pre-order, in-order and post-order.
* 3. Using divide and conquer every TreeNode, do the same procedure on its children.
* 4. Consider the cases if result go negative, do we need change it to 0. for the singlePath
*/
static class MaximumPathSum {
int maxSum;
public int maxPathSum(TreeNode root) {
maxSum = Integer.MIN_VALUE;
visitTree(root);
return maxSum;
}
public int visitTree(TreeNode node){
if(node == null) return 0;
//Divide
int left = visitTree(node.left);
int right = visitTree(node.right);
//Conquer
maxSum = Math.max(maxSum, left + right + node.val);
int singleMax = Math.max(left, right) + node.val;
return singleMax > 0? singleMax : 0;
}
}
static class PathSumToLeaf{
public boolean hasPathSum(TreeNode root, int sum) {
if(root == null) return false;
sum -= root.val;
if(root.left == null && root.right == null && sum == 0) return true;
return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> paths = new ArrayList<>();
List<Integer> path = new ArrayList<>();
pathSum(root, sum, path, paths);
return paths;
}
public void pathSum(TreeNode node, int sum, List<Integer> path, List<List<Integer>> paths){
if(node == null) return;
sum -= node.val;
path.add(node.val);
if(node.left == null && node.right == null && sum == 0){ //found a path
List<Integer> answer = new ArrayList<Integer>();
answer.addAll(path);
paths.add(answer);
} else {
pathSum(node.left, sum, path, paths);
pathSum(node.right, sum, path, paths);
}
path.remove(path.size() - 1);
}
}
}