SvenStack

Tech Share

🧩 Problem Description

Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.
Return the answer in any order.


πŸ’¬ Example

1
2
Input: digits = "23"
Output: ["ad","ae","af","bd","be","bf","cd","ce","cf"]

πŸ’‘ Approach: Backtracking

This is a classic backtracking problem.
Each digit corresponds to a set of characters (phone keypad mapping).
We explore all possible combinations by building strings recursively.

πŸ”’ Java Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.*;

class Solution {
private static final String[] KEYS = {
"", "", "abc", "def", "ghi",
"jkl", "mno", "pqrs", "tuv", "wxyz"
};

public List<String> letterCombinations(String digits) {
List<String> result = new ArrayList<>();
if (digits == null || digits.length() == 0) return result;
backtrack(digits, 0, new StringBuilder(), result);
return result;
}

private void backtrack(String digits, int index, StringBuilder path, List<String> result) {
if (index == digits.length()) {
result.add(path.toString());
return;
}
String letters = KEYS[digits.charAt(index) - '0'];
for (char c : letters.toCharArray()) {
path.append(c);
backtrack(digits, index + 1, path, result);
path.deleteCharAt(path.length() - 1);
}
}
}

⏱ Complexity Analysis

  • Time: O(4^n) β†’ each digit can map to up to 4 letters
  • Space: O(n) recursion depth

✍️ Summary

  • Maps digits to characters based on phone keypad.
  • Uses backtracking to explore all valid combinations.
  • Very common interview question.

Related problems:

  • lc-22 β€” Generate Parentheses
  • lc-39 β€” Combination Sum
  • lc-46 β€” Permutations
  • lc-78 β€” Subsets

🧩 Problem Description

Given an array nums of distinct integers, return all the possible permutations.
You can return the answer in any order.


πŸ’¬ Example

1
2
Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

πŸ’‘ Approach: Backtracking

We use backtracking to generate all permutations by swapping elements or by building a temporary path with used flags.

πŸ”’ Java Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.*;

class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
backtrack(nums, new ArrayList<>(), new boolean[nums.length], result);
return result;
}

private void backtrack(int[] nums, List<Integer> path, boolean[] used, List<List<Integer>> result) {
if (path.size() == nums.length) {
result.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i]) continue;
used[i] = true;
path.add(nums[i]);
backtrack(nums, path, used, result);
path.remove(path.size() - 1);
used[i] = false;
}
}
}

⏱ Complexity Analysis

  • Time: O(n Γ— n!) β†’ each permutation takes O(n) to build, total n! permutations
  • Space: O(n) recursion depth + O(n) used flags

✍️ Summary

  • Classic backtracking problem.
  • Generates all n! permutations.
  • Useful in problems involving ordering, scheduling, or searching solution spaces.

Related problems:

  • lc-47 β€” Permutations II (with duplicates)
  • lc-77 β€” Combinations
  • lc-78 β€” Subsets
  • lc-90 β€” Subsets II

🧩 Problem Description

A trie (pronounced try) or prefix tree is a tree data structure used to efficiently store and search strings in a dataset of strings.

Implement the Trie class:

  • Trie() initializes the object.
  • void insert(String word) inserts the string word into the trie.
  • boolean search(String word) returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.
  • boolean startsWith(String prefix) returns true if there is a previously inserted string word that starts with the given prefix.

πŸ’¬ Example

1
2
3
4
5
6
Input:
["Trie","insert","search","search","startsWith","insert","search"]
[[],["apple"],["apple"],["app"],["app"],["app"],["app"]]

Output:
[null,null,true,false,true,null,true]

πŸ’‘ Approach: Trie Node Structure

We build a tree where each node contains up to 26 children (for each lowercase letter).
Each node also keeps a boolean flag isEnd to mark the end of a word.

πŸ”’ Java Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Trie {
class TrieNode {
TrieNode[] children;
boolean isEnd;

TrieNode() {
children = new TrieNode[26];
isEnd = false;
}
}

private TrieNode root;

public Trie() {
root = new TrieNode();
}

public void insert(String word) {
TrieNode node = root;
for (char c : word.toCharArray()) {
int idx = c - 'a';
if (node.children[idx] == null) {
node.children[idx] = new TrieNode();
}
node = node.children[idx];
}
node.isEnd = true;
}

public boolean search(String word) {
TrieNode node = root;
for (char c : word.toCharArray()) {
int idx = c - 'a';
if (node.children[idx] == null) return false;
node = node.children[idx];
}
return node.isEnd;
}

public boolean startsWith(String prefix) {
TrieNode node = root;
for (char c : prefix.toCharArray()) {
int idx = c - 'a';
if (node.children[idx] == null) return false;
node = node.children[idx];
}
return true;
}
}

⏱ Complexity Analysis

  • Insert: O(L), where L = length of the word
  • Search: O(L)
  • StartsWith: O(P), where P = length of the prefix
  • Space: O(N * L), where N = number of words, L = average word length

✍️ Summary

  • Trie is a powerful data structure for string searching.
  • Operations are efficient: O(L).
  • Widely used in autocomplete, spell check, IP routing, and word games.

Related problems:

  • lc-211 β€” Design Add and Search Words Data Structure
  • lc-212 β€” Word Search II
  • lc-648 β€” Replace Words
  • lc-720 β€” Longest Word in Dictionary

🧩 Problem Description

There are numCourses courses labeled from 0 to numCourses - 1.
You are given an array prerequisites where prerequisites[i] = [a, b] indicates that to take course a you must first take course b.

Return true if you can finish all courses. Otherwise, return false.

This is essentially asking whether the directed graph has a cycle. If there is no cycle, a topological ordering exists and you can finish all courses.


πŸ’¬ Examples

Example 1

1
2
3
Input: numCourses = 2, prerequisites = [[1,0]]
Output: true
Explanation: Take course 0 first, then course 1.

Example 2

1
2
3
Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
Output: false
Explanation: 0 depends on 1 and 1 depends on 0 β†’ cycle.

πŸ’‘ Approach 1: Kahn’s Algorithm (BFS Topological Sort)

  • Build adjacency list and in-degree array.
  • Push all nodes with in-degree 0 into a queue.
  • Pop from queue, decrement in-degree of neighbors, and push any that drop to 0.
  • If we process all nodes, there is no cycle; otherwise, a cycle exists.

πŸ”’ Java Code (BFS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < numCourses; i++) graph.add(new ArrayList<>());

int[] indeg = new int[numCourses];
for (int[] p : prerequisites) {
int a = p[0], b = p[1];
graph.get(b).add(a);
indeg[a]++;
}

Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < numCourses; i++) if (indeg[i] == 0) q.offer(i);

int taken = 0;
while (!q.isEmpty()) {
int cur = q.poll();
taken++;
for (int nxt : graph.get(cur)) {
if (--indeg[nxt] == 0) q.offer(nxt);
}
}
return taken == numCourses;
}
}

πŸ’‘ Approach 2: DFS Cycle Detection (3-color / visiting states)

  • Maintain a state[] array: 0 = unvisited, 1 = visiting, 2 = visited.
  • During DFS, if we reach a node marked visiting (1), we found a cycle.
  • If DFS finishes without back edges, there is no cycle.

πŸ”’ Java Code (DFS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < numCourses; i++) graph.add(new ArrayList<>());
for (int[] p : prerequisites) graph.get(p[1]).add(p[0]);

int[] state = new int[numCourses];
for (int i = 0; i < numCourses; i++) {
if (state[i] == 0 && hasCycle(i, graph, state)) return false;
}
return true;
}

private boolean hasCycle(int u, List<List<Integer>> g, int[] state) {
state[u] = 1; // visiting
for (int v : g.get(u)) {
if (state[v] == 1) return true; // back edge
if (state[v] == 0 && hasCycle(v, g, state)) return true;
}
state[u] = 2; // visited
return false;
}
}

⏱ Time and Space Complexity

  • BFS (Kahn):
    • Time: O(V + E)
    • Space: O(V + E) for graph + queue + indegree
  • DFS:
    • Time: O(V + E)
    • Space: O(V + E) for graph + recursion stack

V = numCourses, E = len(prerequisites).


✍️ Summary

  • The problem reduces to cycle detection in a directed graph.
  • Kahn (BFS) is usually simplest when you just need a yes/no; it also gives a topo order.
  • DFS 3-color is elegant and stack-based.
  • Pick based on your preference and constraints.

Related problems

  • lc-210 β€” Course Schedule II (return topological order)
  • lc-261 β€” Graph Valid Tree (undirected)
  • lc-802 β€” Find Eventual Safe States

🧩 Problem Description

Given an m x n 2D binary grid grid which represents a map of '1's (land) and '0's (water), return the number of islands.

An island is formed by connecting adjacent lands horizontally or vertically.
You may assume all four edges of the grid are surrounded by water.


πŸ’¬ Examples

Example 1

1
2
3
4
5
6
7
Input: grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
Output: 1

Example 2

1
2
3
4
5
6
7
Input: grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
Output: 3

πŸ’‘ Intuition

This is a connected components counting problem on a grid.

  • Each '1' is land.
  • We can run DFS or BFS from every unvisited '1'.
  • Every time we start a new search, it means we found a new island.
  • Mark visited cells as '0' to avoid double counting.

πŸ”’ Java Code (DFS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public int numIslands(char[][] grid) {
int m = grid.length, n = grid[0].length;
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == '1') {
dfs(grid, i, j);
count++;
}
}
}
return count;
}

private void dfs(char[][] grid, int i, int j) {
if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == '0') {
return;
}
grid[i][j] = '0'; // mark visited
dfs(grid, i + 1, j);
dfs(grid, i - 1, j);
dfs(grid, i, j + 1);
dfs(grid, i, j - 1);
}
}

πŸ”„ Alternative Approaches

  • BFS with Queue instead of recursion.
  • Union-Find (Disjoint Set Union): Treat each land cell as a node, union adjacent lands, then count distinct sets.

⏱ Time and Space Complexity

  • Time Complexity: O(m Γ— n) β€” each cell is visited at most once.
  • Space Complexity:
    • O(m Γ— n) worst-case recursion depth (DFS stack).
    • O(min(m, n)) for BFS queue.
    • Union-Find requires O(m Γ— n) extra memory.

✍️ Summary

  • Classic flood fill problem.
  • Each DFS/BFS call explores one island fully.
  • Count how many times we start a new DFS/BFS.

Related problems

  • lc-695 β€” Max Area of Island
  • lc-463 β€” Island Perimeter
  • lc-733 β€” Flood Fill

🧩 Problem Description

You are given an m x n grid where each cell can have one of three values:

  • 0 representing an empty cell,
  • 1 representing a fresh orange,
  • 2 representing a rotten orange.

Every minute, any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten.

Return the minimum number of minutes that must elapse until no cell has a fresh orange.
If it is impossible, return -1.


πŸ’¬ Examples

Example 1

1
2
Input: grid = [[2,1,1],[1,1,0],[0,1,1]]
Output: 4

Example 2

1
2
3
Input: grid = [[2,1,1],[0,1,1],[1,0,1]]
Output: -1
Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten.

Example 3

1
2
Input: grid = [[0,2]]
Output: 0

πŸ’‘ Intuition

This is a multi-source BFS problem.

  • Each rotten orange is a BFS starting point.
  • Use a queue to simulate the spread minute by minute.
  • Track how many fresh oranges remain.
  • If at the end some fresh oranges are left, return -1.

πŸ”’ Java Code (BFS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public int orangesRotting(int[][] grid) {
int m = grid.length, n = grid[0].length;
Queue<int[]> q = new LinkedList<>();
int fresh = 0;

for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 2) {
q.offer(new int[]{i, j});
} else if (grid[i][j] == 1) {
fresh++;
}
}
}

if (fresh == 0) return 0; // no fresh oranges

int minutes = -1;
int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};

while (!q.isEmpty()) {
int size = q.size();
minutes++;
for (int s = 0; s < size; s++) {
int[] cur = q.poll();
for (int[] d : dirs) {
int x = cur[0] + d[0], y = cur[1] + d[1];
if (x < 0 || y < 0 || x >= m || y >= n || grid[x][y] != 1) continue;
grid[x][y] = 2;
fresh--;
q.offer(new int[]{x, y});
}
}
}

return fresh == 0 ? minutes : -1;
}
}

⏱ Time and Space Complexity

  • Time Complexity: O(m Γ— n), each cell is visited at most once.
  • Space Complexity: O(m Γ— n) for the BFS queue.

✍️ Summary

  • Treat all rotten oranges as starting points.
  • Run BFS layer by layer to simulate time passing.
  • Return minutes when all fresh oranges are rotten, otherwise -1.

Related problems

  • lc-286 β€” Walls and Gates
  • lc-542 β€” 01 Matrix
  • lc-200 β€” Number of Islands

🧩 Problem Description

Given the root of a binary tree, return the maximum path sum of the tree.

A path is any sequence of nodes where each pair of adjacent nodes has an edge connecting them.
A path does not need to pass through the root and cannot revisit a node.
The path sum is the sum of node values along the path.


πŸ’¬ Examples

Example 1

1
2
3
Input: root = [1,2,3]
Output: 6
Explanation: The maximum path is 2 β†’ 1 β†’ 3.

Example 2

1
2
3
Input: root = [-10,9,20,null,null,15,7]
Output: 42
Explanation: The maximum path is 15 β†’ 20 β†’ 7.

πŸ’‘ Intuition

At each node, there are two different concepts:

  1. Max Gain to Parent (what we can return upward):
    max(node.val, node.val + leftGain, node.val + rightGain)

    • This represents the best one-side path that can be extended by the parent.
  2. Max Path Through Node (candidate for global answer):
    node.val + max(0, leftGain) + max(0, rightGain)

    • When a path goes through the current node and uses both sides (if beneficial).
    • Negative gains should be treated as 0 (i.e., discard them).

We do a postorder DFS to compute gains bottom-up while maintaining a global maximum.


πŸ”’ Java Code (DFS + Global Tracking)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
private int maxSum = Integer.MIN_VALUE;

public int maxPathSum(TreeNode root) {
gain(root);
return maxSum;
}

private int gain(TreeNode node) {
if (node == null) return 0;

int leftGain = Math.max(0, gain(node.left));
int rightGain = Math.max(0, gain(node.right));

// Path that passes through current node using both sides
int pathThrough = node.val + leftGain + rightGain;
maxSum = Math.max(maxSum, pathThrough);

// Return the max gain to parent: choose one side to extend
return node.val + Math.max(leftGain, rightGain);
}
}

⏱ Time and Space Complexity

  • Time Complexity: O(n) β€” each node is visited once.
  • Space Complexity: O(h) β€” recursion stack, where h is the height of the tree (O(n) worst case).

✍️ Summary

  • Use postorder DFS to compute the best upward gain and update a global maximum with the through-node path.
  • Discard negative gains with Math.max(0, ...) so they don’t depress the total.
  • Classic pattern: **β€œreturn to parent” vs update global answer.

Related problems

  • lc-543 β€” Diameter of Binary Tree (length vs sum idea)
  • lc-687 β€” Longest Univalue Path
  • lc-437 β€” Path Sum III

🧩 Problem Description

Given the root of a binary tree and an integer targetSum, return the number of paths where the sum of the node values in the path equals targetSum.

The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).


πŸ’¬ Example

Example 1

1
2
3
4
5
6
Input: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
Output: 3
Explanation: The paths that sum to 8 are:
- 5 β†’ 3
- 5 β†’ 2 β†’ 1
- -3 β†’ 11

Example 2

1
2
Input: root = [1], targetSum = 1
Output: 1

πŸ’‘ Approach 1: DFS (Brute Force)

The most straightforward solution is:

  • For each node, start a DFS to find all downward paths whose sum equals targetSum.
  • This results in O(nΒ²) time complexity in the worst case.

πŸ”’ Java Code (Brute Force)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int pathSum(TreeNode root, int targetSum) {
if (root == null) return 0;
return countFromNode(root, targetSum)
+ pathSum(root.left, targetSum)
+ pathSum(root.right, targetSum);
}

private int countFromNode(TreeNode node, long targetSum) {
if (node == null) return 0;
int count = 0;
if (node.val == targetSum) count++;
count += countFromNode(node.left, targetSum - node.val);
count += countFromNode(node.right, targetSum - node.val);
return count;
}
}

πŸ’‘ Approach 2: Prefix Sum + HashMap (Optimized)

We can reduce time complexity to O(n) by:

  • Maintaining a prefix sum map that stores (currentSum β†’ frequency).
  • At each node, we calculate how many previous prefix sums satisfy:
    1
    currentSum - targetSum = somePreviousPrefix
  • Update the map during DFS and backtrack after visiting children.

πŸ”’ Java Code (Optimized)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int pathSum(TreeNode root, int targetSum) {
Map<Long, Integer> prefixSumMap = new HashMap<>();
prefixSumMap.put(0L, 1); // Base case: sum = 0 occurs once
return dfs(root, 0L, targetSum, prefixSumMap);
}

private int dfs(TreeNode node, long currSum, int targetSum, Map<Long, Integer> map) {
if (node == null) return 0;

currSum += node.val;
int count = map.getOrDefault(currSum - targetSum, 0);

map.put(currSum, map.getOrDefault(currSum, 0) + 1);

count += dfs(node.left, currSum, targetSum, map);
count += dfs(node.right, currSum, targetSum, map);

map.put(currSum, map.get(currSum) - 1); // backtrack

return count;
}
}

⏱ Time and Space Complexity

Brute Force

  • Time: O(nΒ²) in worst case
  • Space: O(h) recursion stack

Prefix Sum Optimized

  • Time: O(n) β€” visiting each node once
  • Space: O(n) β€” prefix sum map and recursion stack

✍️ Summary

  • Brute Force: Try all starting points β†’ simple but slow.
  • Prefix Sum: Tracks how many ways we can reach targetSum efficiently.
  • Related problems:
    • lc-112 β€” Path Sum
    • lc-113 β€” Path Sum II
    • lc-437 β€” Path Sum III (this one)

🧩 Problem Description

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes p and q.

The lowest common ancestor is defined between two nodes p and q as the lowest node in the tree that has both p and q as descendants (where we allow a node to be a descendant of itself).


πŸ’¬ Example

Example 1

1
2
3
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.

Example 2

1
2
3
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself.

πŸ’‘ Approach: Recursive DFS

We traverse the binary tree recursively:

  • If the current node is null, return null.
  • If the current node matches p or q, return it.
  • Recursively search left and right subtrees.
  • If both left and right return non-null, the current node is the LCA.
  • Otherwise, return the non-null child.

πŸ”’ Java Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {{
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {{
if (root == null || root == p || root == q) {{
return root;
}}

TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);

if (left != null && right != null) {{
return root;
}}

return left != null ? left : right;
}}
}}

⏱ Time and Space Complexity

  • Time Complexity: O(n) β€” visiting each node once
  • Space Complexity: O(h) β€” recursion stack, where h is the tree height

✍️ Summary

  • This is a classic DFS + recursion problem on binary trees.
  • We find the split point where p and q diverge in different subtrees.
  • Related problems:
    • lc-235 β€” LCA of a BST (simpler due to BST property)
    • lc-236 β€” LCA of any binary tree (this one)

🧩 Problem Description

Given two integer arrays preorder and inorder where:

  • preorder is the preorder traversal of a binary tree
  • inorder is the inorder traversal of the same tree

Construct and return the binary tree.


πŸ’¬ Example

1
2
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

πŸ’‘ Approach: DFS + HashMap for Index Lookup

Key Observations:

  1. In preorder traversal, the first element is always the root.
  2. In inorder traversal, elements to the left of root belong to the left subtree, and elements to the right belong to the right subtree.
  3. We can use a HashMap to store value β†’ index mappings in inorder array for O(1) splits.

πŸ”’ Java Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
private Map<Integer, Integer> inorderIndexMap;
private int preorderIndex;

public TreeNode buildTree(int[] preorder, int[] inorder) {
inorderIndexMap = new HashMap<>();
preorderIndex = 0;
for (int i = 0; i < inorder.length; i++) {
inorderIndexMap.put(inorder[i], i);
}
return build(preorder, 0, inorder.length - 1);
}

private TreeNode build(int[] preorder, int left, int right) {
if (left > right) return null;

int rootVal = preorder[preorderIndex++];
TreeNode root = new TreeNode(rootVal);

int inorderIndex = inorderIndexMap.get(rootVal);

root.left = build(preorder, left, inorderIndex - 1);
root.right = build(preorder, inorderIndex + 1, right);

return root;
}
}

⏱ Time and Space Complexity

  • Time Complexity: O(n) β€” each node is created once, and index lookup is O(1).
  • Space Complexity: O(n) β€” for recursion stack and hashmap.

✍️ Summary

  • This is a classic divide and conquer problem.
  • Preorder gives root order, inorder gives subtree boundaries.
  • Related problems:
    • lc-106 β€” Construct from Inorder and Postorder
    • lc-889 β€” Construct from Preorder and Postorder
0%