package com.freetymekiyan.algorithms.level.easy; import com.freetymekiyan.algorithms.utils.Utils.TreeNode; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Given a binary tree, return all root-to-leaf paths. * <p> * For example, given the following binary tree: * <p> * | 1 * | / \ * | 2 3 * | \ * | 5 * All root-to-leaf paths are: * <p> * ["1->2->5", "1->3"] * <p> * Company Tags: Google, Apple, Facebook * Tags: Tree, Depth-first Search * Similar Problems: (M) Path Sum II */ public class BinaryTreePaths { /** * DFS. * The path from root to leaf can be obtained by: * At each node, add its left child's val to the path, traverse the left subtree. * Then add its right child's val to the path, traverse the right subtree. * The base case is when we reach a leaf, we add the path to result. */ public List<String> binaryTreePaths(TreeNode root) { if (root == null) { return Collections.emptyList(); } List<String> paths = new ArrayList<>(); backtrack(root, new StringBuilder(), paths); return paths; } private void backtrack(TreeNode root, StringBuilder path, List<String> paths) { if (root.left == null && root.right == null) { // Reach a leaf. paths.add(path.append(root.val).toString()); return; } path.append(root.val).append("->"); // From empty path. Arrow should be appended before reaching leaf. int len = path.length(); if (root.left != null) { backtrack(root.left, path, paths); path.setLength(len); } if (root.right != null) { backtrack(root.right, path, paths); path.setLength(len); } } /** * DFS. * Recurrence relation: * The paths consist of root + all subtrees paths. * Base case: * If root == null, the resukt list would be empty. * If root is a leaf node, then its value would be in list. * <p> * Just concatenate root's value with those paths returned from subtrees. */ public List<String> binaryTreePaths2(TreeNode root) { if (root == null) { return Collections.emptyList(); } List<String> paths = new ArrayList<>(); if (root.left == null && root.right == null) { paths.add(Integer.toString(root.val)); return paths; } // Paths from left subtree. for (String path : binaryTreePaths2(root.left)) { paths.add(root.val + "->" + path); // Concat root with each path. } // Paths from right subtree. for (String path : binaryTreePaths2(root.right)) { paths.add(root.val + "->" + path); } return paths; } }