Lowest Common Ancestor of a Binary Search Tree, Lowest Common Ancestor of a Binary Tree, Invert Binary Tree, Kth Smallest Element in a BST, Binary Tree Right Side View, Count Complete Tree Nodes
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
1
2
3
4
5
6
7
_______6______
/ \
___2__ ___8__
/ \ / \
0 _4 7 9
/ \
3 5
For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. Another example is LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.
Solution
As long as both p and q are in the same subtree (meaning their values are both smaller or both larger than root’s), move down current node, walks straight from the root to the LCA
1
2
3
4
5
6
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while((p.val-root.val) * (q.val-root.val) > 0){
root = p.val > root.val? root.right : root.left;
}
return root;
}
Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
1
2
3
4
5
6
7
_______3______
/ \
___5__ ___1__
/ \ / \
6 _2 0 8
/ \
7 4
For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
Solution
1
2
3
4
5
6
7
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//if q/p found, return the node, if reached null, return null
Trivia: This problem was inspired by this original tweet by Max Howell: Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.
Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. Note: You may assume k is always valid, 1 ≤ k ≤ BST’s total elements. Follow up: What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine? Hint: Try to utilize the property of a BST. What if you could modify the BST node’s structure? The optimal runtime complexity is O(height of BST).
O(n) Solution
Inorder walk, stop when we get to k elementsm, return the kth.
1
2
3
4
5
6
7
8
9
10
11
12
publicintkthSmallest(TreeNode root, int k) {
ArrayList<Integer> list = new ArrayList<Integer>();
inorder(root, k, list);
return list.get(k-1);
}
privatevoidinorder(TreeNode root, int k, ArrayList<Integer> list){
TreeNodeWithCount rootWithCount = new TreeNodeWithCount(root.val);
rootWithCount.left = buildtree(root.left);
rootWithCount.right = buildtree(root.right);
if (rootWithCount.left != null) rootWithCount.count += rootWithCount.left.count;
if (rootWithCount.right != null) rootWithCount.count += rootWithCount.right.count;
return rootWithCount;
}
publicstatic TreeNodeWithCount findkthsmallest(TreeNodeWithCount root, int k){
int count=0;
if(root.left!=null) count=root.left.count;
if(count>=k){
return findkthsmallest(root.left, k);
}
elseif(count<k-1){
return findkthsmallest(root.right, k-count-1);
}
return root;
}
Binary Tree Right Side View
Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.
1
2
3
4
5
6
7
8
For example:
Given the following binary tree,
1 <---
/ \
23 <---
\ \
54 <---
You should return [1, 3, 4].
Iterative Solution
Reverse BFS,add each layer’s first element to result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res= new ArrayList<Integer>();
if(root==null) return res;
Queue<TreeNode> q = new LinkedList<TreeNode>();
q.offer(root);
while(!q.isEmpty()){
int size = q.size();
for(int i=0;i<size;i++){
TreeNode cur = q.poll();
if(i==0){
res.add(cur.val);
}
if(cur.right!=null){
q.offer(cur.right);
}
if(cur.left!=null){
q.offer(cur.left);
}
}
}
return res;
}
Recursive Solution
Each depth of the tree only select one node.
View depth is current size of result list.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res= new ArrayList<Integer>();
if(root==null) return res;
dfs(res, root, 0);
return res;
}
privatevoiddfs(List<Integer> res, TreeNode r, int level){
if(r==null) return;
if(level==res.size()) {
res.add(r.val);
}
dfs(res, r.right, level+1);
dfs(res, r.left, level+1);
}
Count Complete Tree Nodes
Given a complete binary tree, count the number of nodes. Definition of a complete binary tree from Wikipedia: In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
Solution
Use bit manipulation, faster than Math.pow()
Find the leftmost height and rightmost height, if equal just return the full nodes, if not continue to subtrees