class Solution { private TreeNode getLowestCommonAncestor(TreeNode node, int key1, int key2) { if (node == null) { return null; } if (node.val == key1 || node.val == key2) { return node; } var left = getLowestCommonAncestor(node.left, key1, key2); var right = getLowestCommonAncestor(node.right, key1, key2); if (left == null) { return right; } if (right == null) { return left; } return node; } private record Path(boolean found, StringBuilder path) {} private Path getPath(TreeNode node, int key, StringBuilder path) { if (node == null) { return new Path(false, path); } if (node.val == key) { return new Path(true, path); } // go left path.append('L'); var leftPath = getPath(node.left, key, path); if (leftPath.found) { return leftPath; } path.deleteCharAt(path.length() - 1); // go right path.append('R'); var rightPath = getPath(node.right, key, path); if (rightPath.found) { return rightPath; } path.deleteCharAt(path.length() - 1); return new Path(false, path); } public String getDirections(TreeNode root, int startValue, int destValue) { var commonAncestor = getLowestCommonAncestor(root, startValue, destValue); var pathToStart = getPath(commonAncestor, startValue, new StringBuilder()); var pathToDest = getPath(commonAncestor, destValue, new StringBuilder()); var directions = new StringBuilder(); // gotta go up from the start directions.repeat('U', pathToStart.path.length()); // and then follow the directions down directions.append(pathToDest.path); return directions.toString(); } }