medium Smallest String Starting From Leaf
Problem Statement
You are given a binary tree where each node contains a value between 0 and 25. These values correspond to the letters 'a' to 'z' (0 = 'a', 1 = 'b', ..., 25 = 'z').
Return the lexicographically smallest string that can be formed by starting from a leaf node (a node with no children) and ending at the root of the tree. The string formed should be the lexicographically smallest among all possible strings.
Remember, any shorter prefix of a string is lexicographically smaller. For example, in lexicographical order, "ab" is smaller than "aba".
Examples
Example 1:
- Input: root =
[0, 1, 2, null, 3, 3, 4]
- Expected Output:
"dba" - Explanation: The strings formed from the leaf nodes to the root are "dba", "dca", and "eca". The smallest string is "dba".
Example 2:
- Input: root =
[4, 0, 1, 1, 3, 2, 3]
- Expected Output:
"bae" - Explanation: The strings formed are "bae", "dae", "cbe", and "dbe". The smallest string is "bae".
Example 3:
- Input: root =
[1, 3, 2, 3, 4, 4, 3]
- Expected Output:
"dcb" - Explanation: The strings formed are "ddb", "edb", "ecb", and "dcb". The smallest string is "dcb".
Constraints:
- The number of nodes in the tree is in the range
[1, 8500]. 0 <= Node.val <= 25
Try it yourself
Try solving this question
✅ Solution Smallest String Starting From Leaf
Problem Statement
You are given a binary tree where each node contains a value between 0 and 25. These values correspond to the letters 'a' to 'z' (0 = 'a', 1 = 'b', ..., 25 = 'z').
Return the lexicographically smallest string that can be formed by starting from a leaf node (a node with no children) and ending at the root of the tree. The string formed should be the lexicographically smallest among all possible strings.
Remember, any shorter prefix of a string is lexicographically smaller. For example, in lexicographical order, "ab" is smaller than "aba".
Examples
Example 1:
- Input: root =
[0, 1, 2, null, 3, 3, 4]
- Expected Output:
"dba" - Explanation: The strings formed from the leaf nodes to the root are "dba", "dca", and "eca". The smallest string is "dba".
Example 2:
- Input: root =
[4, 0, 1, 1, 3, 2, 3]
- Expected Output:
"bae" - Explanation: The strings formed are "bae", "dae", "cbe", and "dbe". The smallest string is "bae".
Example 3:
- Input: root =
[1, 3, 2, 3, 4, 4, 3]
- Expected Output:
"dcb" - Explanation: The strings formed are "ddb", "edb", "ecb", and "dcb". The smallest string is "dcb".
Constraints:
- The number of nodes in the tree is in the range
[1, 8500]. 0 <= Node.val <= 25
Solution
To solve this problem, we employ a Depth First Search (DFS) approach to traverse the binary tree from the root to all leaf nodes. As we visit each node, we construct strings by converting the node's value to its corresponding character and appending it to a suffix string. When a leaf node is reached, the constructed string, which represents the path from that leaf to the root, is returned.
The algorithm then compares these strings from different paths, ensuring that the smallest lexicographically string is selected. By using DFS, we efficiently explore all possible paths, and by maintaining the smallest string found so far, we ensure that the final result is the smallest possible string starting from a leaf and moving towards the root.
Step-by-Step Algorithm
-
Start at the Root:
- Start the DFS from the root node.
-
Check for Null Node:
- Inside the
dfsmethod, the first action is to check if the current node (node) isnull. - If the node is
null, return a string with the value"~". This serves as a sentinel value since it is lexicographically larger than any valid string formed by the characters'a'to'z'.
- Inside the
-
Update the Suffix String:
- Convert the value of the current node to its corresponding character by adding the node’s value to the ASCII value of
'a'. - Prepend this character to the
suffixstring as we need to createleaf to rootstring.
- Convert the value of the current node to its corresponding character by adding the node’s value to the ASCII value of
-
Check for Leaf Node:
- If the current node is a leaf, return the current
suffixstring as it represents a valid path from a leaf to the root.
- If the current node is a leaf, return the current
-
Recursive DFS on Child Nodes:
- Recursively call the
dfsmethod on both the left and right children of the current node. - Pass the updated
suffixstring in these recursive calls.
- Recursively call the
-
Compare and Select the Smaller String:
- Compare the strings returned by the left and right recursive calls using the
minimummethod. - The
minimummethod returns the lexicographically smaller string.
- Compare the strings returned by the left and right recursive calls using the
-
Return the Smallest String:
- Return the smallest string obtained from the comparisons. This string is propagated up the recursive call stack, eventually reaching the original call in the
smallestFromLeafmethod.
- Return the smallest string obtained from the comparisons. This string is propagated up the recursive call stack, eventually reaching the original call in the
Algorithm Walkthrough
Given the binary tree structure for the input:
0
/ \
1 2
\ / \
3 3 4
-
Start at Root:
- The
smallestFromLeafmethod is called with the root node (0) and an empty string"".
- The
-
DFS on Root Node:
- The
dfsmethod starts with node0. The currentsuffixis"a"because0 + 'a' = 'a'. - The node
0is not a leaf, so proceed to its children.
- The
-
DFS on Left Subtree (Node
1):- The
dfsmethod is called recursively with node1and the currentsuffix"a". - The current
suffixbecomes"ba"because1 + 'a' = 'b'. - Node
1is not a leaf, so move to its children.
- The
-
DFS on Node
3(Right Child of Node1):- The
dfsmethod is called recursively with node3and the currentsuffix"ba". - The current
suffixbecomes"dba"because3 + 'a' = 'd'. - Node
3is a leaf, so return"dba".
- The
-
DFS on Right Subtree (Node
2):- After completing the left subtree, the algorithm moves to the right subtree by calling
dfson node2with the initialsuffix"a". - The current
suffixbecomes"ca"because2 + 'a' = 'c'. - Node
2is not a leaf, so move to its children.
- After completing the left subtree, the algorithm moves to the right subtree by calling
-
DFS on Node
3(Left Child of Node2):- The
dfsmethod is called recursively with node3and the currentsuffix"ca". - The current
suffixbecomes"dca"because3 + 'a' = 'd'. - Node
3is a leaf, so return"dca".
- The
-
DFS on Node
4(Right Child of Node2):- The
dfsmethod is called recursively with node4and the currentsuffix"ca". - The current
suffixbecomes"eca"because4 + 'a' = 'e'. - Node
4is a leaf, so return"eca".
- The
-
Compare Strings from Right Subtree:
- The algorithm now has two strings from the right subtree:
"dca"and"eca". - Compare these strings using the
minimummethod."dca"is smaller, so"dca"is returned up the call stack.
- The algorithm now has two strings from the right subtree:
-
Compare Left and Right Subtree Results:
- The algorithm compares
"dba"(from the left subtree) and"dca"(from the right subtree) at the root node. "dba"is smaller, so"dba"is returned as the final result.
- The algorithm compares
-
Output the Result:
- The smallest string
"dba"is printed as the output.
- The smallest string
Code
// class TreeNode {
// int val;
// TreeNode left;
// TreeNode right;
// TreeNode(int val) {
// this.val = val;
// }
// }
class Solution {
public String smallestFromLeaf(TreeNode root) {
return dfs(root, "");
}
private String dfs(TreeNode node, String suffix) {
if (node == null) {
return "~";
}
// Append the current node's character to the suffix.
suffix = (char) (node.val + 'a') + suffix;
// If the node is a leaf (no children), return the suffix string.
if (node.left == null && node.right == null) {
return suffix;
}
// Recur for the left and right children and return the lexicographically smaller string.
return minimum(dfs(node.left, suffix), dfs(node.right, suffix));
}
private String minimum(String a, String b) {
return a.compareTo(b) < 0 ? a : b;
}
public static void main(String[] args) {
Solution solution = new Solution();
TreeNode root = new TreeNode(0);
root.left = new TreeNode(1);
root.right = new TreeNode(2);
root.left.right = new TreeNode(3);
root.right.left = new TreeNode(3);
root.right.right = new TreeNode(4);
System.out.println(solution.smallestFromLeaf(root)); // Expected output: "dba"
}
}
Complexity Analysis
Time Complexity
- The time complexity of the algorithm is
, where Nis the number of nodes in the binary tree. - This is because the algorithm performs a Depth First Search (DFS), which visits each node exactly once.
Space Complexity
- The space complexity is
, where His the height of the tree. - This space is required for the recursive stack used during DFS. In the worst case, if the tree is skewed, the height
Hcould be equal toN, leading to a space complexity of. - In the best case, the tree is balanced, and the space complexity would be
.
🤖 Don't fully get this? Learn it with Claude
Stuck on Smallest String Starting From Leaf? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Smallest String Starting From Leaf** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Smallest String Starting From Leaf** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Smallest String Starting From Leaf**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Smallest String Starting From Leaf**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.