← Back to Blog
1. LC 236 – Lowest Common Ancestor of a Binary Tree Medium
Companies: Meta, Amazon, Microsoft, Google
Problem: Given a binary tree, find the lowest common ancestor (LCA) of two given nodes p and q.
Intuition & Diagram
Using Post-Order DFS traversal, recursively explore left and right subtrees. If a node matches p or q, return it. If both left and right return non-null pointers, the current node is the LCA.
3 <-- LCA (Returns 3 because left has 5 and right has 1)
/ \
5 1
/ \
6 2
p=5, q=1 => LCA is 3
C++ Code
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root || root == p || root == q) return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if (left && right) return root;
return left ? left : right;
}
};
Time: O(N)
Space: O(H) recursion stack
2. LC 124 – Binary Tree Maximum Path Sum Hard
Companies: Meta, Amazon, Google
Problem: Find the maximum path sum in a binary tree. A path is defined as any sequence of nodes following parent-child connections.
Intuition & Diagram
For each node, compute the max path extending downwards into the left and right subtrees. Ignore negative contributions (clamp to 0). The max path passing through the current node as a root curve is left + right + root->val.
-10
/ \
9 20
/ \
15 7
Max Path = 15 + 20 + 7 = 42
C++ Code
class Solution {
int maxSum = INT_MIN;
int maxGain(TreeNode* node) {
if (!node) return 0;
int leftGain = max(maxGain(node->left), 0);
int rightGain = max(maxGain(node->right), 0);
int currentPath = node->val + leftGain + rightGain;
maxSum = max(maxSum, currentPath);
return node->val + max(leftGain, rightGain);
}
public:
int maxPathSum(TreeNode* root) {
maxGain(root);
return maxSum;
}
};
3. LC 297 – Serialize and Deserialize Binary Tree Hard
Companies: Meta, Google, Uber
Problem: Design an algorithm to serialize a binary tree to a string and deserialize that string back to the original tree.
Intuition & Diagram
Use Pre-Order Traversal (Root-Left-Right) with # representing null nodes and commas separating values. Deserialization uses a stringstream queue to rebuild the tree recursively.
1
/ \
2 3 => Encoded String: "1,2,#,#,3,4,#,#,5,#,#"
/ \
4 5
C++ Code
class Codec {
public:
string serialize(TreeNode* root) {
if (!root) return "#,";
return to_string(root->val) + "," + serialize(root->left) + serialize(root->right);
}
TreeNode* deserialize(string data) {
stringstream ss(data);
return buildTree(ss);
}
private:
TreeNode* buildTree(stringstream& ss) {
string val;
getline(ss, val, ',');
if (val == "#") return nullptr;
TreeNode* root = new TreeNode(stoi(val));
root->left = buildTree(ss);
root->right = buildTree(ss);
return root;
}
};
4. LC 863 – All Nodes Distance K in Binary Tree Medium
Companies: Amazon, Meta, Netflix
Problem: Return an array of values of all nodes that have a distance k from the target node.
Intuition & Diagram
Convert the binary tree into an undirected graph by tracking parent pointers using a hash map. Perform a Breadth-First Search (BFS) starting from the target node up to radial depth k.
Target = 5, K = 2
3
/ \
5* 1 => BFS outwards: Level 1 -> {3, 6, 2}
/ \ / \ Level 2 -> {7, 4, 1} (Result: [7, 4, 1])
6 2 0 8
/ \
7 4
C++ Code
class Solution {
unordered_map parent;
void markParents(TreeNode* root) {
queue q;
q.push(root);
while(!q.empty()){
TreeNode* curr = q.front(); q.pop();
if(curr->left) { parent[curr->left] = curr; q.push(curr->left); }
if(curr->right) { parent[curr->right] = curr; q.push(curr->right); }
}
}
public:
vector distanceK(TreeNode* root, TreeNode* target, int k) {
markParents(root);
unordered_map visited;
queue q;
q.push(target);
visited[target] = true;
int dist = 0;
while(!q.empty()){
if(dist++ == k) break;
int size = q.size();
for(int i = 0; i < size; i++){
TreeNode* curr = q.front(); q.pop();
if(curr->left && !visited[curr->left]) { q.push(curr->left); visited[curr->left] = true; }
if(curr->right && !visited[curr->right]) { q.push(curr->right); visited[curr->right] = true; }
if(parent[curr] && !visited[parent[curr]]) { q.push(parent[curr]); visited[parent[curr]] = true; }
}
}
vector res;
while(!q.empty()){ res.push_back(q.front()->val); q.pop(); }
return res;
}
};
5. LC 987 – Vertical Order Traversal of a Binary Tree Hard
Companies: Meta, Amazon, Bloomberg
Problem: Return the vertical order traversal of nodes in a binary tree from left to right, ordered top to bottom, with overlapping nodes sorted by value.
Intuition & Diagram
Assign coordinates (col, row) to each node. Use BFS with a multiset structure map>> to keep node coordinates automatically sorted.
col: -1 0 1
3 (0,0)
/ \
(1,-1)9 20 (1,1)
/ \
(2,0) 15 7 (2,2)
Result: [[9], [3, 15], [20], [7]]
C++ Code
class Solution {
public:
vector> verticalTraversal(TreeNode* root) {
map>> nodes;
queue>> q;
q.push({root, {0, 0}});
while(!q.empty()) {
auto p = q.front(); q.pop();
TreeNode* node = p.first;
int x = p.second.first, y = p.second.second;
nodes[x][y].insert(node->val);
if(node->left) q.push({node->left, {x - 1, y + 1}});
if(node->right) q.push({node->right, {x + 1, y + 1}});
}
vector> ans;
for(auto& p : nodes) {
vector col;
for(auto& q : p.second) {
col.insert(col.end(), q.second.begin(), q.second.end());
}
ans.push_back(col);
}
return ans;
}
};
Time: O(N log N)
Space: O(N)
6. LC 437 – Path Sum III Medium
Companies: Amazon, Microsoft, Target
Problem: Find the number of paths in a binary tree where the sum of node values along the path equals targetSum.
Intuition & Diagram
Use a Prefix Sum Hash Map combined with DFS traversal. If currentSum - targetSum exists in the map, it indicates a valid path segment ending at the current node.
10 (Prefix sum: 10)
/
5 (Prefix sum: 15) Target = 8
/
3 (Prefix sum: 18) -> 18 - 8 = 10 (Found in Hash Map! Path: 5 -> 3)
C++ Code
class Solution {
unordered_map prefixMap;
int count = 0;
void dfs(TreeNode* node, long long currSum, int target) {
if (!node) return;
currSum += node->val;
if (prefixMap.find(currSum - target) != prefixMap.end()) {
count += prefixMap[currSum - target];
}
prefixMap[currSum]++;
dfs(node->left, currSum, target);
dfs(node->right, currSum, target);
prefixMap[currSum]--; // Backtrack
}
public:
int pathSum(TreeNode* root, int targetSum) {
prefixMap[0] = 1;
dfs(root, 0, targetSum);
return count;
}
};
7. LC 114 – Flatten Binary Tree to Linked List Medium
Companies: Meta, Microsoft, Adobe
Problem: Flatten the tree into a linked list in-place using pre-order traversal order.
Intuition & Diagram
Morris Traversal concept: For any node with a left child, find its in-order predecessor (rightmost node in the left subtree), connect its right pointer to node->right, then shift node->left to node->right.
1 1
/ \ \
2 5 => 2
/ \ \ \
3 4 6 3 ... -> 6
C++ Code
class Solution {
public:
void flatten(TreeNode* root) {
TreeNode* curr = root;
while (curr) {
if (curr->left) {
TreeNode* prev = curr->left;
while (prev->right) prev = prev->right;
prev->right = curr->right;
curr->right = curr->left;
curr->left = nullptr;
}
curr = curr->right;
}
}
};
Time: O(N)
Space: O(1) auxiliary
8. LC 105 – Construct Binary Tree from Preorder and Inorder Traversal Medium
Companies: Amazon, Google, Microsoft
Problem: Given preorder and inorder traversal arrays, construct and return the binary tree.
Intuition & Diagram
The first element of preorder is always the root. Locate this root in the inorder array using a hash map to determine left and right subtrees sizes, then construct recursively.
Preorder = [3, 9, 20, 15, 7] (3 is Root)
Inorder = [9, |3|, 15, 20, 7] (Left subtree: [9], Right subtree: [15, 20, 7])
C++ Code
class Solution {
unordered_map inMap;
TreeNode* build(vector& pre, int preStart, int preEnd,
vector& in, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd) return nullptr;
TreeNode* root = new TreeNode(pre[preStart]);
int inRoot = inMap[root->val];
int numsLeft = inRoot - inStart;
root->left = build(pre, preStart + 1, preStart + numsLeft, in, inStart, inRoot - 1);
root->right = build(pre, preStart + numsLeft + 1, preEnd, in, inRoot + 1, inEnd);
return root;
}
public:
TreeNode* buildTree(vector& preorder, vector& inorder) {
for(int i = 0; i < inorder.size(); i++) inMap[inorder[i]] = i;
return build(preorder, 0, preorder.size() - 1, inorder, 0, inorder.size() - 1);
}
};
9. LC 662 – Maximum Width of Binary Tree Medium
Companies: Google, Amazon, Bloomberg
Problem: Find the maximum width of a binary tree (maximum number of nodes between the leftmost and rightmost non-null nodes at any level).
Intuition & Diagram
Assign heap-like indices to nodes (Left child: 2*i, Right child: 2*i + 1). To prevent integer overflow, normalize indices by subtracting the level's minimum index at each BFS layer.
1 (idx:0)
/ \
3 2 (Level width: 2 - 1 + 1 = 2)
/ \ \
5 3 9 (indices: 0, 1, 3 -> Width = 3 - 0 + 1 = 4)
C++ Code
class Solution {
public:
int widthOfBinaryTree(TreeNode* root) {
if (!root) return 0;
unsigned long long maxWidth = 0;
queue> q;
q.push({root, 0});
while (!q.empty()) {
int size = q.size();
unsigned long long minIdx = q.front().second;
unsigned long long first = 0, last = 0;
for (int i = 0; i < size; i++) {
unsigned long long currIdx = q.front().second - minIdx;
TreeNode* node = q.front().first;
q.pop();
if (i == 0) first = currIdx;
if (i == size - 1) last = currIdx;
if (node->left) q.push({node->left, 2 * currIdx + 1});
if (node->right) q.push({node->right, 2 * currIdx + 2});
}
maxWidth = max(maxWidth, last - first + 1);
}
return maxWidth;
}
};
10. LC 2385 – Amount of Time for Binary Tree to Be Infected Medium
Companies: Amazon, Google
Problem: Return the number of minutes needed for the entire tree to be infected starting from a given target node value.
Intuition & Diagram
Convert the binary tree to an adjacency graph or compute depth relative to the infection node using DFS. The infection spreads 1 edge per minute, equivalent to finding the maximum distance from the target node.
1 (t=2)
/ \
(t=1) 5 3 (t=3)
\ \
(t=0)[4] 10 (t=4) -> Total Time = 4
C++ Code
class Solution {
unordered_map> adj;
void buildGraph(TreeNode* node, TreeNode* parent) {
if (!node) return;
if (parent) {
adj[node->val].push_back(parent->val);
adj[parent->val].push_back(node->val);
}
buildGraph(node->left, node);
buildGraph(node->right, node);
}
public:
int amountOfTime(TreeNode* root, int start) {
buildGraph(root, nullptr);
queue q;
unordered_set visited;
q.push(start);
visited.insert(start);
int time = -1;
while (!q.empty()) {
time++;
int size = q.size();
while (size--) {
int curr = q.front(); q.pop();
for (int neighbor : adj[curr]) {
if (!visited.count(neighbor)) {
visited.insert(neighbor);
q.push(neighbor);
}
}
}
}
return time;
}
};