8.Tree
1.Maximum Depth of Binary Tree
求最大depth,很简单:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int maxDepth(TreeNode root) {
if(root==null){
return 0;
}
return findDepth(root,1);
}
public int findDepth(TreeNode node,int num){
int left=Integer.MIN_VALUE,right=Integer.MIN_VALUE;
if(node.left==null&&node.right==null){
return num;
}
if(node.left!=null){
left = findDepth(node.left,num+1);
}
if(node.right!=null){
right = findDepth(node.right,num+1);
}
num = Math.max(left,right);
return num;
}
}
关于java位运算符(<<,>>):
1.<<:左移运算符,num << n,相当于num乘以2的n次方,如3<<4=48。
2.>>:右移运算符,num >> n,相当于num除以2的n次方,如32>>4=2。
2.Count Complete Tree Nodes
计算一颗完全二叉树的nodes数。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
//success 1
//可能timeOut,每次都需要计算height,所以很慢
// class Solution {
// int height(TreeNode root) {
// return root == null ? -1 : 1 + height(root.left);
// }
// public int countNodes(TreeNode root) {
// int h = height(root);
// return h < 0 ? 0 :
// //如果相差1,说明左边是完全二叉树,那么加左半边
// //如果不相差1,说明左边不是完全二叉树,那么加上上半部分,将root下移。
// height(root.right) == h-1 ? (1 << h) + countNodes(root.right)
// : (1 << h-1) + countNodes(root.left);
// }
// }
//success 2
class Solution {
int height(TreeNode root) {
return root == null ? -1 : 1 + height(root.left);
}
public int countNodes(TreeNode root) {
int nodes = 0, h = height(root);
while (root != null) {
if (height(root.right) == h - 1) {
nodes += 1 << h;
root = root.right;
} else {
nodes += 1 << h-1;
root = root.left;
}
h--;
}
return nodes;
}
}
可参考Concise Java solutions O(log(n)^2)。
3.Serialize and Deserialize BST
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.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root==null){
return "error";
}
List list = preorderTraversal(root);
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i));
sb.append(",");
}
return sb.toString().substring(0,sb.length()-1);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if("error".equals(data)){
return null;
}
String[] array = data.split(",");
TreeNode root = new TreeNode(Integer.valueOf(array[0]));
for (int i=1;i<array.length;i++){
TreeNode node = new TreeNode(Integer.valueOf(array[i]));
findPlace(node,root);
}
return root;
}
void findPlace(TreeNode node,TreeNode root){
if(node.val<root.val){
if(root.left==null){
root.left=node;
}else{
findPlace(node,root.left);
}
}else{
if(root.right==null){
root.right=node;
}else{
findPlace(node,root.right);
}
}
}
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
//Stack is a subclass of Vector that implements a standard last-in, first-out stack.
Stack<TreeNode> stack = new Stack<>();
//用stack来记录right
while(root!=null){
list.add(root.val);
//处理right
if(root.right!=null){
stack.push(root.right);
}
//处理left
root = root.left;
if(root==null&&!stack.isEmpty()){
root = stack.pop();
}
}
return list;
}
}
4.Unique Binary Search Trees
受Count Number of Binary Search Tree Possible given n keys Dynamic Programming的启发,采用DP的思想来计算。
public class Solution {
public int numTrees(int n) {
int[] dp = new int[n+1];
dp[0] = 1;
dp[1] = 1;
for (int i = 1; i <= n; i++) {
calDpM(dp,i);
}
return dp[n];
}
void calDpM(int[] dp,int m){
int sum=0;
for (int i = 0; i <= m-1; i++) {
sum+=dp[i]*dp[m-1-i];
}
dp[m] = sum;
}
}
5.Binary Tree Inorder Traversal
实现二叉树的中序遍历。跟前面2.Binary Tree Preorder Traversal
实现的前序遍历思路一样,也是有递归和迭代两种解法(当然,迭代肯定要难一点)。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
//success 1
//recusive method
// public class Solution {
// public List<Integer> inorderTraversal(TreeNode root) {
// List<Integer> list = new ArrayList<>();
// if(root==null){
// return list;
// }
// recursive(list,root);
// return list;
// }
// void recursive(List list,TreeNode node){
// if(node.left!=null){
// recursive(list,node.left);
// }
// list.add(node.val);
// if(node.right!=null){
// recursive(list,node.right);
// }
// }
// }
//success 2
//iterative method
public class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = root;
while(cur!=null || !stack.empty()){
while(cur!=null){
stack.add(cur);
cur = cur.left;
}
cur = stack.pop();
list.add(cur.val);
cur = cur.right;
}
return list;
}
}
6.Binary Tree Postorder Traversal
有了前面的前序和中序遍历,我们乘热打铁把后序遍历的两种方法也实现了吧!
前序遍历的顺序:root-left-right
中序遍历的顺序:left-root-right
后序遍历的顺序:left-right-root
注意到后序遍历与前序遍历之间的关系,将前序遍历中left与right互换,然后将结果reverse就得到了后序(trick)。所以在前序遍历的基础上改动:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
//success 1
//recusive method
public class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root==null){
return list;
}
recursive(list,root);
return list;
}
void recursive(List list,TreeNode node){
if(node.left!=null){
recursive(list,node.left);
}
if(node.right!=null){
recursive(list,node.right);
}
list.add(node.val);
}
}
//success 2
//iterative method
// public class Solution {
// public List<Integer> postorderTraversal(TreeNode root) {
// List<Integer> list = new ArrayList<>();
// //Stack is a subclass of Vector that implements a standard last-in, first-out stack.
// Stack<TreeNode> stack = new Stack<>();
// //用stack来记录left
// while(root!=null){
// list.add(root.val);
// //处理left
// if(root.left!=null){
// stack.push(root.left);
// }
// //处理right
// root = root.right;
// if(root==null&&!stack.isEmpty()){
// root = stack.pop();
// }
// }
// Collections.reverse(list);
// return list;
// }
// }
关于三种顺序的迭代算法总结:Preorder, Inorder, and Postorder Iteratively Summarization。