一、可出算法
二、解决
1. 二叉树的深度
递归
public int TreeDepth(TreeNode root) {
if(root == null)
return 0;
int leftDepth = TreeDepth(root.left); // 左子树深度
int rightDepth = TreeDepth(root.ight); // 右子树深度
int depth = 1 + max(leftDepth, rightDepth); // 当前节点的深度
return depth;
}
// 简写:
public int TreeDepth(TreeNode root) {
if(root == null)
return 0;
return Math.max(TreeDepth(root.left), TreeDepth(root.right)) + 1;
}
层序遍历
public int TreeDepth(TreeNode root) {
if(root == null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int res = 0;
while(!queue.isEmpty()){
Queue<TreeNode> temp = new LinkedList<>(); // 需要一个临时队列存储
for(TreeNode node:queue){
if(node.left!=null) temp.add(node.left);
if(node.right!=null) temp.add(node.right);
}
queue = temp; // 赋值
res++;
}
return res;
}
2. 按之字形顺序打印二叉树
栈
- 栈,先进后出;设置标识位,记录
从左往右
还是从右往左
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
if(pRoot == null) return res;
boolean flag = true;
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
stack1.add(pRoot);
while(!stack1.isEmpty() || !stack2.isEmpty()) {
ArrayList<Integer> line = new ArrayList<>();
if(flag) {
while(!stack1.isEmpty()) {
TreeNode pop = stack1.pop();
line.add(pop.val);
if(pop.left != null) stack2.add(pop.left);
if(pop.right != null) stack2.add(pop.right);
}
} else {
while(!stack2.isEmpty()) {
TreeNode pop = stack2.pop();
line.add(pop.val);
if(pop.right != null) stack1.add(pop.right);
if(pop.left != null) stack1.add(pop.left);
}
}
res.add(line);
flag = !flag;
}
return res;
}
3. 二叉搜索树的第k小个节点
- 二叉搜索树:中序遍历(左根右)是从小到大的排序序列
- 延伸:若要得到二叉搜索树的第K大节点,将“左根右”的顺序换成“右根左”即可
递归
int res = -1, k = -1;
public int KthNode (TreeNode proot, int k) {
if(proot == null) return -1;
this.k = k;
dfs(proot);
return res;
}
void dfs(TreeNode root) {
if(root == null || k <= 0) return; //当root为空或者已经找到了res时,直接返回
dfs(root.left);
if(--k == 0){ //先--,再判断
res = root.val;
return; //这里的 return 可以避免之后的无效迭代dfs(root.left);
}
dfs(root.right);
}
迭代
public int KthNode (TreeNode proot, int k) {
if(proot == null) return -1;
Stack<TreeNode> stack = new Stack<>();
stack.push(proot);
TreeNode cur = proot;
while(!stack.isEmpty()) {
// 先找到左子树的最左子节点
while(cur.left != null) {
stack.push(cur.left);
cur = cur.left;
}
k--;
TreeNode temp = stack.pop();
if(0 == k) return temp.val;
if(temp.right != null) {
stack.push(temp.right);
cur = temp.right;
}
}
return -1;
}
4. 重建二叉树
递归
public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
if(pre == null || pre.length <=0 || vin == null || vin.length <=0 || pre.length != vin.length)
return null;
int len = pre.length;
return buildTree(pre, vin, 0, len-1, 0, len-1);
}
private TreeNode buildTree(int[] pre, int[] in, int preLeft, int preRight, int inLeft, int inRight) {
if(preLeft > preRight || inLeft > inRight) return null;
int preRoot = pre[preLeft];
TreeNode root = new TreeNode(preRoot);
int index;
for(index = inLeft; index < inRight; index++) {
if(preRoot == in[index]) break;
}
int len = index - inLeft;
root.left = buildTree(pre, in, preLeft + 1, preLeft + len, inLeft, inLeft + len -1);
root.right = buildTree(pre, in, preLeft + len + 1, preRight, inLeft + len + 1, inRight);
return root;
}
迭代
- 剑指 Offer:重建二叉树
public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
if(pre == null || pre.length <=0 || vin == null || vin.length <=0 || pre.length != vin.length)
return null;
int len = pre.length;
TreeNode root = new TreeNode(pre[0]);
LinkedList<TreeNode> stack = new LinkedList<>();
stack.push(root);
int index = 0;
for(int i = 1; i < len; i++) {
int preVal = pre[i];
TreeNode node = stack.peek();
if(node.val != vin[index]) {
node.left = new TreeNode(preVal);
stack.push(node.left);
} else {
while(!stack.isEmpty() && stack.peek().val == vin[index]) {
node = stack.pop();
index++;
}
node.right = new TreeNode(preVal);
stack.push(node.right);
}
}
return root;
}
5、树的子结构
递归
- 剑指 Offer:树的子结构
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root1 == null || root2 == null) return false;
return check(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}
private boolean check(TreeNode root1, TreeNode root2) {
if(root2 == null) return true;
if(root1 == null || root1.val != root2.val) return false;
return check(root1.left, root2.left) && check(root1.right, root2.right);
}