Tree

Ace your homework & exams now with Quizwiz!

// iterative public boolean isSymmetric(TreeNode root) { Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); queue.add(root); while(!queue.isEmpty()) { TreeNode t1 = queue.poll(); TreeNode t2 = queue.poll(); if(t1 == null && t2 == null) continue; if(t1 == null || t2 == null) return false; if(t1.val != t2.val) return false; queue.add(t1.left); queue.add(t2.right); queue.add(t1.right); queue.add(t2.left); } return true; } // recursive version public boolean isSymmetric(TreeNode root) { return isMirror(root, root); } private boolean isMirror(TreeNode t1, TreeNode t2) { if(t1 == null && t2 == null) return true; if(t1 == null || t2 == null) return false; return t1.val == t2.val && isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left); }

101. Symmetric Tree Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For example, this binary tree [1,2,2,3,4,4,3] is symmetric: 1 / \ 2 2 / \ / \ 3 4 4 3 But the following [1,2,2,null,3,null,3] is not: 1 / \ 2 2 \ \ 3 3 Note: Bonus points if you could solve it both recursively and iteratively.

public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> result = new ArrayList<>(); if(root == null) return result; Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); while(!queue.isEmpty()) { int size = queue.size(); List<Integer> tmpList = new ArrayList<>(); for(int i = 0; i < size; i++) { TreeNode curr = queue.poll(); tmpList.add(curr.val); if(curr.left != null) { queue.add(curr.left); } if(curr.right != null) { queue.add(curr.right); } } result.add(new ArrayList<>(tmpList)); } return result; }

102. Binary Tree Level Order Traversal Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). For example: Given binary tree [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 return its level order traversal as: [ [3], [9,20], [15,7] ]

public List<List<Integer>> zigzagLevelOrder(TreeNode root) { List<List<Integer>> result = new ArrayList<>(); if(root == null) return result; Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); boolean zigzag = false; while(!queue.isEmpty()) { int size = queue.size(); List<Integer> tmpList = new ArrayList<>(); for(int i = 0; i < size; i++) { TreeNode curr = queue.poll(); if(!zigzag) { tmpList.add(curr.val); } else { tmpList.add(0, curr.val); } if(curr.left != null) { queue.add(curr.left); } if(curr.right != null) { queue.add(curr.right); } } result.add(new ArrayList<>(tmpList)); zigzag = !zigzag; } return result; }

103. Binary Tree Zigzag Level Order Traversal Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). For example: Given binary tree [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 return its zigzag level order traversal as: [ [3], [20,9], [15,7] ]

public int maxDepth(TreeNode root) { if(root == null) return 0; Stack<TreeNode> stack = new Stack<>(); Stack<Integer> depth = new Stack<>(); stack.add(root); depth.add(1); int currDepth = 0; int depthSoFar = 0; while(!stack.isEmpty()) { TreeNode curr = stack.pop(); currDepth = depth.pop(); if(curr != null) { depthSoFar = Math.max(depthSoFar, currDepth); if(curr.left != null) { stack.add(curr.left); depth.add(currDepth + 1); } if(curr.right != null) { stack.add(curr.right); depth.add(currDepth + 1); } } } return depthSoFar; }

104. Maximum Depth of Binary Tree Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. Note: A leaf is a node with no children. Example: Given binary tree [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 return its depth = 3.

public TreeNode sortedArrayToBST(int[] num) { if (num.length == 0) return null; return sortedArrayToBST(num, 0, num.length - 1); } public TreeNode sortedArrayToBST(int[] num, int start, int end) { if (start > end) return null; int mid = (start + end) / 2; TreeNode root = new TreeNode(num[mid]); root.left = sortedArrayToBST(num, start, mid - 1); root.right = sortedArrayToBST(num, mid + 1, end); return root; }

108. Convert Sorted Array to Binary Search Tree Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

public boolean isBalanced(TreeNode root) { if(root == null) return true; if(root.left == null && root.right == null) return true; int leftHeight = getHeight(root.left); int rightHeight = getHeight(root.right); return Math.abs(leftHeight - rightHeight) < 2 && isBalanced(root.left) && isBalanced(root.right); } private int getHeight(TreeNode root) { // An empty tree has height -1 if(root == null) return -1; return 1 + Math.max(getHeight(root.left), getHeight(root.right)); }

110. Balanced Binary Tree Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as: a binary tree in which the depth of the two subtrees of every node never differ by more than 1. Example 1: Given the following tree [3,9,20,null,null,15,7]: 3 / \ 9 20 / \ 15 7 Return true. Example 2: Given the following tree [1,2,2,3,3,null,null,4,4]: 1 / \ 2 2 / \ 3 3 / \ 4 4 Return false.

public int minDepth(TreeNode root) { if(root == null) return 0; Queue<TreeNode> queue = new LinkedList<>(); Queue<Integer> counts = new LinkedList<>(); queue.add(root); counts.add(1); while(!queue.isEmpty()) { TreeNode curr = queue.poll(); int count = counts.poll(); if(curr.left == null && curr.right == null) { return count; } if(curr.left != null) { queue.add(curr.left); counts.add(count + 1); } if(curr.right != null) { queue.add(curr.right); counts.add(count + 1); } } return 0; }

111. Minimum Depth of Binary Tree Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. Note: A leaf is a node with no children. Example: Given binary tree [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 return its minimum depth = 2.

public boolean hasPathSum(TreeNode root, int sum) { if(root == null) return false; if(root.val == sum && (root.left == null && root.right == null)) { return true; } return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val); }

112. Path Sum Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. Note: A leaf is a node with no children. Example: Given the below binary tree and sum = 22, 5 / \ 4 8 / / \ 11 13 4 / \ \ 7 2 1 return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.

public List<List<Integer>> pathSum(TreeNode root, int sum) { List<List<Integer>> result = new ArrayList<>(); List<Integer> currList = new ArrayList<>(); if(root == null) return result; pathSum(root, sum, result, currList); return result; } private void pathSum(TreeNode root, int sum, List<List<Integer>> result, List<Integer> currList) { if(root == null) { return; } if(root.left == null && root.right == null) { if(root.val == sum) { currList.add(root.val); result.add(new ArrayList<>(currList)); currList.remove(currList.size() - 1); } } currList.add(root.val); pathSum(root.left, sum - root.val, result, currList); pathSum(root.right, sum - root.val, result, currList); currList.remove(currList.size() - 1); }

113. Path Sum II Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. Note: A leaf is a node with no children. Example: Given the below binary tree and sum = 22, 5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1 Return: [ [5,4,11,2], [5,8,4,5] ]

public Node connect(Node root) { if(root == null) return null; Queue<Node> queue = new LinkedList<>(); queue.add(root); while(!queue.isEmpty()) { int size = queue.size(); for(int i = 0; i < size; i++) { Node curr = queue.poll(); if(i < size - 1) { curr.next = queue.peek(); } if(curr.left != null) { queue.add(curr.left); } if(curr.right != null) { queue.add(curr.right); } } } return root; }

117. Populating Next Right Pointers in Each Node II Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL. Initially, all next pointers are set to NULL. Note: You may only use constant extra space. Recursive approach is fine, implicit stack space does not count as extra space for this problem. You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children). Example: Given the following perfect binary tree, 1 / \ 2 3 / \ / \ 4 5 6 7 After calling your function, the tree should look like: 1 -> NULL / \ 2 -> 3 -> NULL / \ / \ 4->5->6->7 -> NULL

public List<Integer> postorderTraversal(TreeNode root) { Stack<TreeNode> stack = new Stack<>(); List<Integer> result = new ArrayList<>(); if(root == null) return result; stack.push(root); while(!stack.isEmpty()) { TreeNode curr = stack.pop(); result.add(0, curr.val); if(curr.left != null) { stack.add(curr.left); } if(curr.right != null) { stack.add(curr.right); } } return result; }

145. Binary Tree Postorder Traversal Given a binary tree, return the postorder traversal of its nodes' values. Example: Input: [1,null,2,3] 1 \ 2 / 3 Output: [3,2,1] Follow up: Recursive solution is trivial, could you do it iteratively?

public TreeNode upsideDownBinaryTree(TreeNode root) { TreeNode prev = null; TreeNode tmp = null; while (root != null) { TreeNode next = root.left; root.left = tmp; tmp = root.right; root.right = prev; prev = root; root = next; } return prev; }

156. Binary Tree Upside Down Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that shares the same parent node) or empty, flip it upside down and turn it into a tree where the original right nodes turned into left leaf nodes. Return the new root. Example: Input: [1,2,3,4,5] 1 / \ 2 3 / \ 4 5 Output: return the root of the binary tree [4,5,2,#,#,3,1] 4 / \ 5 2 / \ 3 1

int i = 1; public boolean verifyPreorder(int[] A) { return A.length == 0 || check(A, Integer.MIN_VALUE, A[0]) && check(A, A[0], Integer.MAX_VALUE); } public boolean check(int[] A, int left, int right) { if (i == A.length || A[i] > right) return true; int mid = A[i++]; return (mid > left) && check(A, left, mid) && check(A, mid, right); }

255. Verify Preorder Sequence in Binary Search Tree Given an array of numbers, verify whether it is the correct preorder traversal sequence of a binary search tree. You may assume each number in the sequence is unique. Consider the following binary search tree: 5 / \ 2 6 / \ 1 3 Example 1: Input: [5,2,6,1,3] Output: false

public int closestValue(TreeNode root, double target) { int closest = root.val; while(root != null) { closest = Math.abs(root.val - target) < Math.abs(closest - target) ? root.val : closest; if(root.val < target) { root = root.right; } else { root = root.left; } } return closest; }

270. Closest Binary Search Tree Value Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target. Note: Given target value is a floating point. You are guaranteed to have only one unique value in the BST that is closest to the target. Example: Input: root = [4,2,5,1,3], target = 3.714286 4 / \ 2 5 / \ 1 3 Output: 4

public List<Integer> closestKValues(TreeNode root, double target, int k) { LinkedList<Integer> result = new LinkedList<>(); collect(root, target, k, result); return result; } private void collect(TreeNode root, double target, int k, LinkedList<Integer> result) { if(root == null) return; collect(root.left, target, k, result); if(result.size() == k) { if(Math.abs(target - root.val) < Math.abs(target - result.peekFirst())) { result.remove(0); } else return; } result.add(root.val); collect(root.right, target, k, result); }

272. Closest Binary Search Tree Value II Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target. Note: Given target value is a floating point. You may assume k is always valid, that is: k ≤ total nodes. You are guaranteed to have only one unique set of k values in the BST that are closest to the target. Example: Input: root = [4,2,5,1,3], target = 3.714286, and k = 2 4 / \ 2 5 / \ 1 3 Output: [4,3] Follow up:Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?

public TreeNode inorderSuccessor(TreeNode root, TreeNode p) { TreeNode candidate = null; while(root != null) { if(root.val > p.val) { candidate = root; root = root.left; } else { root = root.right; } } return candidate; }

285. Inorder Successor in BST Given a binary search tree and a node in it, find the in-order successor of that node in the BST. The successor of a node p is the node with the smallest key greater than p.val. Example 1: Input: root = [2,1,3], p = 1 Output: 2 Explanation: 1's in-order successor node is 2. Note that both p and the return value is of TreeNode type.

public class Codec { // Encodes a tree to a single string. public String serialize(TreeNode root) { StringBuilder sb = new StringBuilder(); serialize(root, sb); return sb.toString(); } private void serialize(TreeNode root, StringBuilder sb) { if(root == null) { sb.append("X").append(","); return; } sb.append(root.val); sb.append(","); serialize(root.left, sb); serialize(root.right, sb); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { if(data == null || "".equals(data)) return null; String[] vals = data.split(","); Queue<String> queue = new LinkedList<>(); queue.addAll(Arrays.asList(vals)); return deserialize(queue); } private TreeNode deserialize(Queue<String> queue) { String node = queue.poll(); if(node.equals("X")) { return null; } TreeNode root = new TreeNode(Integer.valueOf(node)); root.left = deserialize(queue); root.right = deserialize(queue); return root; } }

297. Serialize and Deserialize Binary Tree Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment. Design an algorithm to serialize and deserialize a binary search tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary search tree can be serialized to a string and this string can be deserialized to the original tree structure. The encoded string should be as compact as possible. Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.

Just very intuitive depth-first search, send cur node value to the next level and compare it with the next level node. private int max = 0; public int longestConsecutive(TreeNode root) { if(root == null) { return 0; } helper(root, 0, root.val); return max; } public void helper(TreeNode root, int cur, int target) { if(root == null) return; if(root.val == target) cur++; else cur = 1; max = Math.max(cur, max); helper(root.left, cur, root.val + 1); helper(root.right, cur, root.val + 1); }

298. Binary Tree Longest Consecutive Sequence Given a binary tree, find the length of the longest consecutive sequence path. The path refers to any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The longest consecutive path need to be from parent to child (cannot be the reverse). Example 1: Input: 1 \ 3 / \ 2 4 \ 5 Output: 3 Explanation: Longest consecutive sequence path is 3-4-5, so return 3.

public List<Integer> inorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<>(); if(root == null) return result; Stack<TreeNode> stack = new Stack<>(); TreeNode curr = root; while(curr != null || !stack.isEmpty()) { while(curr != null) { stack.push(curr); curr = curr.left; } curr = stack.pop(); result.add(curr.val); curr = curr.right; } return result; }

94. Binary Tree Inorder Traversal Given a binary tree, return the inorder traversal of its nodes' values. Example: Input: [1,null,2,3] 1 \ 2 / 3 Output: [1,3,2] Follow up: Recursive solution is trivial, could you do it iteratively?

public List<TreeNode> generateTrees(int n) { if(n==0){ return new ArrayList<TreeNode>(); } return helper(1, n); } public List<TreeNode> helper(int m, int n){ List<TreeNode> result = new ArrayList<TreeNode>(); if(m>n){ result.add(null); return result; } for(int i=m; i<=n; i++){ List<TreeNode> ls = helper(m, i-1); List<TreeNode> rs = helper(i+1, n); for(TreeNode l: ls){ for(TreeNode r: rs){ TreeNode curr = new TreeNode(i); curr.left=l; curr.right=r; result.add(curr); } } } return result; }

95. Unique Binary Search Trees II Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ... n. Example: Input: 3 Output: [ [1,null,3,2], [3,2,null,1], [3,1,null,null,2], [2,1,3], [1,null,2,null,3] ] Explanation: The above output corresponds to the 5 unique BST's shown below: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3

public boolean isValidBST(TreeNode root) { return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE); } public boolean isValidBST(TreeNode root, long min, long max) { if(root == null) return true; if(root.val <= min || root.val >= max) return false; return isValidBST(root.left, min, root.val) && isValidBST(root.right, root.val, max); }

98. Validate Binary Search Tree Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes with keys greater than the node's key. Both the left and right subtrees must also be binary search trees. Example 1: 2 / \ 1 3 Input: [2,1,3] Output: true

Inorder traversal will return values in an increasing order. So if an element is less than its previous element, the previous element is a swapped node. public class Solution { TreeNode first; TreeNode second; TreeNode pre; public void inorder(TreeNode root){ if(root == null) return; inorder(root.left); if(pre == null){ pre = root; } else { if(root.val < pre.val){ if(first == null){ first = pre; } second = root; } pre = root; } inorder(root.right); } public void recoverTree(TreeNode root) { if(root == null) return; inorder(root); if(second != null && first != null){ int val = second.val; second.val = first.val; first.val = val; } } }

99. Recover Binary Search Tree Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing its structure.

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(!covers(root, p) || !covers(root, q)) return null; if(root == null || root == p || root == q) return root; boolean isPOnLeft = covers(root.left, p); boolean isQOnLeft = covers(root.left, q); if(isPOnLeft != isQOnLeft) return root; if(isPOnLeft) return lowestCommonAncestor(root.left, p, q); else return lowestCommonAncestor(root.right, p, q); } private boolean covers(TreeNode root, TreeNode p) { if(root == null) return false; if(root == p) return true; return covers(root.left, p) || covers(root.right, p); }

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 p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself)." Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5] _______6______ / \ ___2__ ___8__ / \ / \ 0 _4 7 9 / \ 3 5 Example 1: Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 Output: 6 Explanation: The LCA of nodes 2 and 8 is 6. Example 2: Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 Output: 2 Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.

public int kthSmallest(TreeNode root, int k) { Stack<TreeNode> toExplore = new Stack<>(); // iterate all the way to the left while(root != null) { toExplore.push(root); root = root.left; } while(k != 0) { TreeNode curr = toExplore.pop(); k--; if(k == 0) return curr.val; // if k is still not 0 // go one right and iterate all the way left again TreeNode right = curr.right; while(right != null) { toExplore.push(right); right = right.left; } } return -1; }

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. Example 1: Input: root = [3,1,4,null,2], k = 1 3 / \ 1 4 \ 2 Output: 1

// iterative public int sumNumbers(TreeNode root) { if(root == null) return 0; Stack<TreeNode> stack = new Stack<>(); stack.push(root); Stack<Integer> runningSum = new Stack<>(); runningSum.push(root.val); int totalSum = 0; while(!stack.isEmpty()) { TreeNode curr = stack.pop(); int currSum = runningSum.pop(); if(curr.left != null) { stack.push(curr.left); runningSum.push(currSum * 10 + curr.left.val); } if(curr.right != null) { stack.push(curr.right); runningSum.push(currSum * 10 + curr.right.val); } if(curr.left == null && curr.right == null) { totalSum = totalSum + currSum; } } return totalSum; } // recursive public int sumNumbers(TreeNode root) { return sumNumbers(root, 0); } public int sumNumbers(TreeNode root, int sum) { if(root == null) { return 0; } int totalSoFar = sum * 10 + root.val; if(root.left == null && root.right == null) return totalSoFar; return sumNumbers(root.left, totalSoFar) + sumNumbers(root.right, totalSoFar); }

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. Note: A leaf is a node with no children. Example: Input: [1,2,3] 1 / \ 2 3 Output: 25 Explanation: The root-to-leaf path 1->2 represents the number 12. The root-to-leaf path 1->3 represents the number 13. Therefore, sum = 12 + 13 = 25. Example 2: Input: [4,9,0,5,1] 4 / \ 9 0 / \ 5 1 Output: 1026 Explanation: The root-to-leaf path 4->9->5 represents the number 495. The root-to-leaf path 4->9->1 represents the number 491. The root-to-leaf path 4->0 represents the number 40. Therefore, sum = 495 + 491 + 40 = 1026.

public int maxDepth(TreeNode root) { if(root==null) return 0; int leftDepth = maxDepth(root.left); int rightDepth = maxDepth(root.right); int bigger = Math.max(leftDepth, rightDepth); return bigger + 1; }

Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

public int maxDepth(TreeNode root) { if(root == null) return 0; return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); }

Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. Note: A leaf is a node with no children. Example: Given binary tree [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 return its depth = 3.

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(!covers(root, p) || !covers(root, q)) return null; return ancestorHelper(root, p, q); } private TreeNode ancestorHelper(TreeNode root, TreeNode p, TreeNode q) { if(root == null || root == p || root == q) return root; boolean pOnLeft = covers(root.left, p); boolean qOnLeft = covers(root.left, q); if(pOnLeft != qOnLeft) { return root; } TreeNode childSide = pOnLeft ? root.left : root.right; return ancestorHelper(childSide, p, q); } private boolean covers(TreeNode root, TreeNode p) { if(root == null) return false; if(root == p) return true; return covers(root.left, p) || covers(root.right, p); }

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 p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself)." Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4] _______3______ / \ ___5__ ___1__ / \ / \ 6 _2 0 8 / \ 7 4 Example 1: Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 Output: 3 Explanation: The LCA of of nodes 5 and 1 is 3. Example 2: 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 according to the LCA definition. Note: All of the nodes' values will be unique. p and q are different and both values will exist in the binary tree.

// It is a DFS so you need stack. Don't forget to set the left child to null public void flatten(TreeNode root) { if(root == null) return; Stack<TreeNode> stack = new Stack<>(); stack.push(root); while(!stack.isEmpty()) { TreeNode curr = stack.pop(); if(curr.right != null) { stack.push(curr.right); } if(curr.left != null) { stack.push(curr.left); } if(!stack.isEmpty()) { curr.right = stack.peek(); } curr.left = null; } }

Given a binary tree, flatten it to a linked list in-place. For example, given the following tree: 1 / \ 2 5 / \ \ 3 4 6 The flattened tree should look like: 1 \ 2 \ 3 \ 4 \ 5 \ 6

// Iterative solution public List<Integer> rightSideView(TreeNode root) { List<Integer> result = new ArrayList<>(); if(root == null) return result; Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); while(queue.size() > 0){ //get size here int size = queue.size(); for(int i = 0; i < size; i++){ TreeNode top = queue.remove(); //the first element in the queue (right-most of the tree) if(i == 0){ result.add(top.val); } //add right first if(top.right != null){ queue.add(top.right); } //add left if(top.left != null){ queue.add(top.left); } } } return result; } // recursion public List<Integer> rightSideView(TreeNode root) { List<Integer> res = new ArrayList<>(); helper(root,0,res); return res; } void helper(TreeNode rt, int h, List<Integer> res){ if(rt == null) return; if(h >= res.size()) res.add(rt.val); helper(rt.right, h+1,res); helper(rt.left, h+1,res); }

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. Example: Input: [1,2,3,null,5,null,4] Output: [1, 3, 4] Explanation: 1 <--- / \ 2 3 <--- \ \ 5 4 <---

public List<String> binaryTreePaths(TreeNode root) { List<String> answer = new ArrayList<String>(); if (root != null) searchBT(root, "", answer); return answer; } private void searchBT(TreeNode root, String path, List<String> answer) { if (root.left == null && root.right == null) answer.add(path + root.val); if (root.left != null) searchBT(root.left, path + root.val + "->", answer); if (root.right != null) searchBT(root.right, path + root.val + "->", answer); }

Given a binary tree, return all root-to-leaf paths. Note: A leaf is a node with no children. Example: Input: 1 / \ 2 3 \ 5 Output: ["1->2->5", "1->3"] Explanation: All root-to-leaf paths are: 1->2->5, 1->3

For each node, its left child's degree is -1 and is right child's degree is +1. We can do a level order traversal and save the degree information. public List<List<Integer>> verticalOrder(TreeNode root) { List<List<Integer>> result = new ArrayList<List<Integer>>(); if(root==null) { return result; } // level and list HashMap<Integer, List<Integer>> map = new HashMap<>(); Queue<TreeNode> queue = new LinkedList<TreeNode>(); Queue<Integer> level = new LinkedList<Integer>(); queue.offer(root); level.offer(0); int minLevel = 0; int maxLevel = 0; while(!queue.isEmpty()) { TreeNode p = queue.poll(); int curr = level.poll(); //track min and max levels minLevel = Math.min(minLevel, curr); maxLevel = Math.max(maxLevel, curr); if (map.containsKey(curr)) { map.get(curr).add(p.val); } else { List<Integer> list = new ArrayList<Integer>(); list.add(p.val); map.put(curr, list); } if (p.left != null) { queue.offer(p.left); level.offer(curr - 1); } if (p.right != null) { queue.offer(p.right); level.offer(curr + 1); } } for(int i = minLevel; i <= maxLevel; i++) { if(map.containsKey(i)) { result.add(map.get(i)); } } return result; }

Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column).

public int countNodes(TreeNode root) { if(root == null) return 0; int left = height(root); if(left < 0) return 0; if(height(root.right) == left - 1) { return (int) Math.pow(2, left) + countNodes(root.right); } return (int) Math.pow(2, left - 1) + countNodes(root.left); } private int height(TreeNode root){ if(root == null) return -1; return 1 + height(root.left); }

Given a complete binary tree, count the number of nodes. Note: 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. Example: Input: 1 / \ 2 3 / \ / 4 5 6 Output: 6

public int closestValue(TreeNode root, double target) { int closest = 0; double min = Double.MAX_VALUE; while(root != null) { double diff = Math.abs(target - root.val); if(diff < min) { min = diff; closest = root.val; } if(root.val < target) { root = root.right; } else if(root.val > target) { root = root.left; } else return root.val; } return closest; }

Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.

static ListNode h; public TreeNode sortedListToBST(ListNode head) { if (head == null) return null; h = head; int len = getLength(head); return sortedListToBST(0, len - 1); } // get list length public int getLength(ListNode head) { int len = 0; ListNode p = head; while (p != null) { len++; p = p.next; } return len; } // build tree bottom-up public TreeNode sortedListToBST(int start, int end) { if (start > end) return null; // mid int mid = (start + end) / 2; TreeNode left = sortedListToBST(start, mid - 1); TreeNode root = new TreeNode(h.val); h = h.next; TreeNode right = sortedListToBST(mid + 1, end); root.left = left; root.right = right; return root; }

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

The problem can be solved in a dynamic programming way. Given a sorted sequence 1 ... n, to construct a Binary Search Tree (BST) out of the sequence, we could enumerate each number i in the sequence, and use the number as the root, then, the subsequence 1 ... (i-1) on its left side would lay on the left branch of the root, and similarly the right subsequence (i+1) ... n lay on the right branch of the root. We then can construct the subtree from the subsequence recursively. Through the above approach, we could be assured that the BST that we construct are all unique, since they start from unique roots. As we can see, the problem can be reduced into problems with smaller sizes, instead of recursively (also repeatedly) solve the subproblems, we can store the solution of subproblems and reuse them later, i.e. the dynamic programming way. public int numTrees(int n) { int[] G = new int[n + 1]; G[0] = 1; G[1] = 1; for (int i = 2; i <= n; ++i) { for (int j = 1; j <= i; ++j) { G[i] += G[j - 1] * G[i - j]; } } return G[n]; }

Given n, how many structurally unique BST's (binary search trees) that store values 1 ... n? Example: Input: 3 Output: 5 Explanation: Given n = 3, there are a total of 5 unique BST's: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3

The basic idea is here: Say we have 2 arrays, PRE and IN. Preorder traversing implies that PRE[0] is the root node. Then we can find this PRE[0] in IN, say it's IN[5]. Now we know that IN[5] is root, so we know that IN[0] - IN[4] is on the left side, IN[6] to the end is on the right side. Recursively doing this on subarrays, we can build a tree out of it :) Hope this helps. public TreeNode buildTree(int[] preorder, int[] inorder) { return helper(0, 0, inorder.length - 1, preorder, inorder); } public TreeNode helper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder) { if (preStart > preorder.length - 1 || inStart > inEnd) { return null; } TreeNode root = new TreeNode(preorder[preStart]); int inIndex = 0; // Index of current root in inorder for (int i = inStart; i <= inEnd; i++) { if (inorder[i] == root.val) { inIndex = i; } } root.left = helper(preStart + 1, inStart, inIndex - 1, preorder, inorder); root.right = helper(preStart + inIndex - inStart + 1, inIndex + 1, inEnd, preorder, inorder); return root; }

Given preorder and inorder traversal of a tree, construct the binary tree. Note: You may assume that duplicates do not exist in the tree. For example, given preorder = [3,9,20,15,7] inorder = [9,3,15,20,7] Return the following binary tree: 3 / \ 9 20 / \ 15 7

public boolean isSameTree(TreeNode p, TreeNode q) { if(!check(p, q)) return false; Queue<TreeNode> pExplore = new LinkedList<>(); pExplore.add(p); Queue<TreeNode> qExplore = new LinkedList<>(); qExplore.add(q); while(!pExplore.isEmpty() && !qExplore.isEmpty()) { TreeNode currP = pExplore.poll(); TreeNode currQ = qExplore.poll(); if(!check(currP, currQ)) return false; if(currP != null) { if(!check(currP.left, currQ.left)) return false; if(currP.left != null) { pExplore.add(currP.left); qExplore.add(currQ.left); } if(!check(currP.right, currQ.right)) return false; if(currP.right != null) { pExplore.add(currP.right); qExplore.add(currQ.right); } } } return true; } private boolean check(TreeNode p, TreeNode q) { if(p == null && q == null) return true; if(p == null || q == null) return false; if(p.val == q.val) return true; return false; }

Given two binary trees, write a function to check if they are the same or not. Two binary trees are considered the same if they are structurally identical and the nodes have the same value. Recursion version is obvious, do it in iterative way. Example 1: Input: 1 1 / \ / \ 2 3 2 3 [1,2,3], [1,2,3] Output: true

// recursive public TreeNode invertTree(TreeNode root) { if(root == null) return null; TreeNode leftNode = invertTree(root.left); TreeNode rightNode = invertTree(root.right); root.left = rightNode; root.right = leftNode; return root; } // iterative public TreeNode invertTree(TreeNode root) { if(root == null) return null; if(root.left == null && root.right == null) return root; Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); while(!queue.isEmpty()) { TreeNode curr = queue.remove(); TreeNode tmp = curr.left; curr.left = curr.right; curr.right = tmp; if(curr.right != null) { queue.add(curr.right); } if(curr.left != null) { queue.add(curr.left); } } return root; }

Invert a binary tree. Example: Input: 4 / \ 2 7 / \ / \ 1 3 6 9 Output: 4 / \ 7 2 / \ / \ 9 6 3 1 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 f*** off.

In a binary tree, if we consider null as leaves, then all non-null node provides 2 outdegree and 1 indegree (2 children and 1 parent), except root all null node provides 0 outdegree and 1 indegree (0 child and 1 parent). Suppose we try to build this tree. During building, we record the difference between out degree and in degree diff = outdegree - indegree. When the next node comes, we then decrease diff by 1, because the node provides an in degree. If the node is not null, we increase diff by 2, because it provides two out degrees. If a serialization is correct, diff should never be negative and diff will be zero when finished. public boolean isValidSerialization(String preorder) { String[] nodes = preorder.split(","); int diff = 1; for (String node: nodes) { // decrement indegree node by one diff--; if (diff < 0) return false; // increment outdegree node by two if (!node.equals("#")) diff += 2; } return diff == 0; } video: https://www.youtube.com/watch?v=_mbnPPHJmTQ

One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, we record the node's value. If it is a null node, we record using a sentinel value such as #. _9_ / \ 3 2 / \ / \ 4 1 # 6 / \ / \ / \ # # # # # # For example, the above binary tree can be serialized to the string "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents a null node. Given a string of comma separated values, verify whether it is a correct preorder traversal serialization of a binary tree. Find an algorithm without reconstructing the tree. Each comma separated value in the string must be either an integer or a character '#' representing null pointer. You may assume that the input format is always valid, for example it could never contain two consecutive commas such as "1,,3". Example 1: Input: "9,3,4,#,#,1,#,#,2,#,6,#,#" Output: true Example 2: Input: "1,#" Output: false

public boolean isSameTree(TreeNode p, TreeNode q) { if(p==null && q==null){ return true; }else if(p==null || q==null){ return false; } if(p.val==q.val){ return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); }else{ return false; } }

Two binary trees are considered the same if they have identical structure and nodes have the same value.

public int pathSum(TreeNode root, int sum) { if (root == null) return 0; return pathSumFrom(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum); } private int pathSumFrom(TreeNode node, int sum) { if (node == null) return 0; return (node.val == sum ? 1 : 0) + pathSumFrom(node.left, sum - node.val) + pathSumFrom(node.right, sum - node.val); }

You are given a binary tree in which each node contains an integer value. Find the number of paths that sum to a given value. 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). The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000. Example: root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 10 / \ 5 -3 / \ \ 3 2 11 / \ \ 3 -2 1 Return 3. The paths that sum to 8 are: 1. 5 -> 3 2. 5 -> 2 -> 1 3. -3 -> 11


Related study sets

Significant Figures, Kinematics, & Dynamics

View Set

All Science Definition & Formula Grade 8

View Set

Chapter 15: Assets - Inventory and Operations Management

View Set

Ch 54: Drugs Acting on the Upper Respiratory Tract

View Set