问题列表:
利用DFS解决:
Binary Trees (Pre-order, In-order and Post-order) Traversal
Binary Trees‘s Largest Depth
222. Count Complete Tree Nodes
114. Flatten Binary Tree to Linked List
250. Count Univalue Subtrees
298. Binary Tree Longest Consecutive Sequence
297. Serialize and Deserialize Binary Tree
366. Find Leaves of Binary Tree
利用BFS解决:
199. Binary Tree Right Side View
314. Binary Tree Vertical Order Traversal
Binary Trees (Pre-order, In-order and Post-order) Traversal:
See this article: http://blog.csdn.net/firehotest/article/details/58535905
Binary Trees‘s Largest Depth:
使用Divide and Conquer
需要思考好最极端最小的情况返回什么, 分治只是把问题处理的数据分小了,问题还是不变的。所以这里的处理方法还是Math.max(两个返回值)。
public class Solution {
/**
* @param root: The root of binary tree.
* @return: An integer.
*/
// private static depth = 0;
public int maxDepth(TreeNode root) {
// write your code here
if(root == null){//why this is the termination? because you don't need to consider the left and right children
return 0;
}
int temp1 = maxDepth(root.left);
int temp2 = maxDepth(root.right);
return 1+Math.max(temp1,temp2);
}
}
计算完全的二叉树的节点数目(Completed Binary Tree)
222. Count Complete Tree Nodes:
利用满二叉树的高度和节点个数的性质:2^(h) - 1
We should use the feature of full binary tree. If a full binary tree’s height is h, then there are 2^(h) - 1 nodes in this tree. Then this problem can divide into two sub situations.
If the most left height is equal to the right height, it is a full binary tree. We can use the 2^(h) - 1 to return the height. Otherwise, recursively call the same function for left sub tree and right sub tree.
public class Solution {
private int leftHeight(TreeNode root) {
int count = 1;
while (root.left != null) {
count++;
root = root.left;
}
return count;
}
private int rightHeight(TreeNode root) {
int count = 1;
while (root.right != null) {
count++;
root = root.right;
}
return count;
}
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
int height = 0;
if ((height = leftHeight(root)) == rightHeight(root)) {// full binary tree
return (1 << height) - 1;
} else {
return 1 + countNodes(root.left) + countNodes(root.right);
}
}
}
利用前序遍历的顺序把一个数扁平化成一个链表
114. Flatten Binary Tree to Linked List
Given a binary tree, flatten it to a linked list in-place.
For example,
Given
1
/ \
2 5
/ \ \
3 4 6
The flattened tree should look like:
1
\
2
\
3
\
4
\
5
\
6
错误的一点:当你把右子孩子存好放进stack后,然后把左孩子赋给右孩子后,记得把左节点变成Null,不然整棵树变得很奇怪。
public class Solution {
public void flatten(TreeNode root) {
if (root == null) {
return;
}
TreeNode tmp = root;
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
while (tmp != null || !stack.isEmpty()) {
while (tmp.left != null) {
if (tmp.right != null) {
TreeNode rightSub = tmp.right;
stack.addFirst(rightSub);
}
tmp.right = tmp.left;
tmp.left = null;// 错误点1
tmp = tmp.right;
}
if (tmp.right != null) {
tmp = tmp.right;
} else {
if (!stack.isEmpty()) {//错误点2
tmp.right = stack.removeFirst();
}
tmp = tmp.right;
}
}
}
}
利用DFS递归解决的题目:
250. Count Univalue Subtrees
Given a binary tree, count the number of uni-value subtrees.
A Uni-value subtree means all nodes of the subtree have the same value.
For example:
Given binary tree,
5
/ \
1 5
/ \ \
5 5 5
return 4.
思路:每一个点都可以以当前点作为root,然后进行DFS判断是否是Uni-value的子树。递归的函数只要传进一个值,每个点都判断一次即可。
public class Solution {
private boolean recursion(TreeNode root, int val) {
if (root.val != val) {
return false;
}
if (root.left == null && root.right == null) {
return true;
}
if (root.left != null && root.right != null) {
return recursion(root.left, val) && recursion(root.right, val);
} else if (root.left != null) {
return recursion(root.left, val);
} else {
return recursion(root.right, val);
}
}
public int countUnivalSubtrees(TreeNode root) {
if (root == null) {
return 0;
}
if (recursion(root, root.val)) {
return 1 + countUnivalSubtrees(root.left) + countUnivalSubtrees(root.right);
} else {
return countUnivalSubtrees(root.left) + countUnivalSubtrees(root.right);
}
}
}
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).
For example,
1
\
3
/ \
2 4
\
5
Longest consecutive sequence path is 3-4-5, so return 3.
2
\
3
/
2
/
1
Longest consecutive sequence path is 2-3,not3-2-1, so return 2.
public class Solution {
private int longest = 0;
private void recursion (TreeNode root, TreeNode prev, int length) {
if (prev == null || prev.val + 1 == root.val) {
length = length + 1;
} else {
length = 1;
}
longest = length > longest ? length : longest;
if (root.left == null && root.right == null) {
return;
}
if (root.left != null && root.right != null) {
recursion(root.left, root, length);
recursion(root.right, root, length);
} else if (root.left != null) {
recursion(root.left, root, length);
} else if (root.right != null) {
recursion(root.right, root, length);
}
}
public int longestConsecutive(TreeNode root) {
if (root == null) {//别忘了处理extreme cases
return 0;
}
recursion(root, null, 0);
return longest;
}
}
通过一个Serialize的前序字符序列重构一棵树,前提是对于null的节点有专门的符号表示,这里我用"null"表示。注意,利用toString打印容器的话,元素和元素之间除了逗号,还有space。不要忽略这些细节。重构一棵树,最好还是用递归,否则很困难。
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 tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
For example, you may serialize the following tree
1
/ \
2 3
/ \
4 5
as "[1,2,3,null,null,4,5]", just the same as how LeetCode OJ serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
public class Codec {
private void traversal(TreeNode root, List<String> rec) {
if (root == null) {
rec.add("null");
return;
}
rec.add(String.valueOf(root.val));
traversal(root.left, rec);
traversal(root.right, rec);
return;
}
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
List<String> rec = new ArrayList<>();
traversal(root, rec);
String res = rec.toString();
return res.substring(1, res.length() - 1);
}
private TreeNode buildTree(LinkedList<String> nodes) {
if (nodes.isEmpty()) {
return null;
}
String node = nodes.removeFirst();
node = node.trim();//注意从集合打印出来的string元素之间除了逗号,还有空格
if (node.equals("null")) {
return null;
}
TreeNode cur = new TreeNode(Integer.valueOf(node));
cur.left = buildTree(nodes);
cur.right = buildTree(nodes);
return cur;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] strNodes = data.split(",");
LinkedList<String> nodes = new LinkedList<>(Arrays.asList(strNodes));
return buildTree(nodes);
}
}
366. Find Leaves of Binary Tree
Given a binary tree, collect a tree's nodes as if you were doing this: Collect and remove all leaves, repeat until the tree is empty.
Example:
Given binary tree
1
/ \
2 3
/ \
4 5
Returns [4, 5, 3], [2], [1].
//递归函数做的事情:
//如果是null,返回-1。然后把当前节点的level = 1 + Max(左右节点的返回值)。
//然后一点trick的地方在于:当前结果集的size就是当前需要记录的level值,需要创建一个新的ArrayList放进答案集里面。
public class Solution {
private int recursion(TreeNode root, List<List<Integer>> ans) {
if (root == null) {
return -1;
}
int left = recursion(root.left, ans);
int right = recursion(root.right, ans);
int level = 1 + Math.max(left, right);
if (level == ans.size()) {
List<Integer> tmp = new ArrayList<>();
tmp.add(root.val);
ans.add(tmp);
} else {
ans.get(level).add(root.val);
}
return level;
}
public List<List<Integer>> findLeaves(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
recursion(root, ans);
return ans;
}
}
199. 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.
For example:
Given the following binary tree,
1 <---
/ \
2 3 <---
\ \
5 4 <---
You should return [1, 3, 4].
思路:利用BFS,每次把当前层最后一个节点放进答案集了。注意,一般二叉树的BFS问题的模板都是用Null作为层与层之间的间隔,来区别。需要注意的是,如果当stack为空的时候就不要再放Null了,否则陷入死循环。
public class Solution {
public List<Integer> rightSideView(TreeNode root) {
// 使用BFS,将每层的最后的元素加入答案集
Queue<TreeNode> buff = new LinkedList<>();
List<Integer> ans = new LinkedList<>();
if (root == null) {
return ans;
}
buff.offer(root);
buff.offer(null);
while (!buff.isEmpty()) {
TreeNode tmp = null;
while ((tmp = buff.poll()) != null) {
if (buff.peek() == null) {
ans.add(tmp.val);
}
if (tmp.left != null) {
buff.offer(tmp.left);
}
if (tmp.right != null) {
buff.offer(tmp.right);
}
}
if (!buff.isEmpty()) {// 错误1
buff.offer(null);
}
}
return ans;
}
}
314. Binary Tree Vertical Order Traversal
Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column).
If two nodes are in the same row and column, the order should be from left to right.
Examples:
Given binary tree [3,9,20,null,null,15,7],
3
/\
/ \
9 20
/\
/ \
15 7
return its vertical order traversal as:
[
[9],
[3,15],
[20],
[7]
]
思路:先记录下来root属于哪个level。然后用TreeMap记录每个level有哪些节点。接着,遍历TreeMap的所有Value即可。需要注意,题目要求from top to bottom, from left to right. 所以必须使用BFS,否则同一个level的才可以保证from top to bottom的顺序。
public class Solution {
private int detectRootPosit (TreeNode root) {
TreeNode tmp = root;
int left = 0;
while (tmp.left != null) {
left = left + 1;
tmp = tmp.left;
}
return left;
}
public List<List<Integer>> verticalOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
if (root == null) {
return ans;
}
Map<Integer, List<Integer>> levNodes = new TreeMap<Integer, List<Integer>>();
int location = detectRootPosit(root);
Queue<TreeNode> buff = new LinkedList<>();
Queue<Integer> level = new LinkedList<>();
buff.offer(root);
level.offer(location);
while (!buff.isEmpty()) {
TreeNode tmp = buff.poll();
int lev = level.poll();
if (levNodes.containsKey(lev)) {
levNodes.get(lev).add(tmp.val);
} else {
List<Integer> tmpList = new ArrayList<>();
tmpList.add(tmp.val);
levNodes.put(lev, tmpList);
}
if (tmp.left != null) {
buff.offer(tmp.left);
level.offer(lev - 1);
}
if (tmp.right != null) {
buff.offer(tmp.right);
level.offer(lev + 1);
}
}
for (int key : levNodes.keySet()) {
ans.add(levNodes.get(key));
}
return ans;
}
}