Outline
1.Binary Tree DFS Traversal
- preorder / inorder / postorder
- Divide & Conquer
- DFS Template
2.Binary Tree BFS Traversal
- BFS template
3. Binary Search Tree
- validate, insert, delete
note:二叉树问题,首选分治(天然分治场景,解决80%问题);
1.1 DFS模板
模板一:
递归;
public class Solution {
public void traverse(TreeNode root) {
if (root == null) {
return;
}
// do something with root
traverse(root.left);
// do something with root
traverse(root.right);
// do something with root
}
}
模板二:
分治思想;
Tempate 2: Divide & Conquer
public class Solution {
public ResultType traversal(TreeNode root) {
// null or leaf
if (root == null) {
// do something and return;
}
// Divide
ResultType left = traversal(root.left);
ResultType right = traversal(root.right);
// Conquer
ResultType result = Merge from left and right.
return result;
}
}
练习题:
T-1 二叉树前序遍历
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
解法一:递归
public class Solution {
public ArrayList<Integer> preorderTraversal(TreeNode root) {
ArrayList<Integer> result = new ArrayList<Integer>();
traverse(root, result);
return result;
}
// 把root为跟的preorder加入result里面
private void traverse(TreeNode root, ArrayList<Integer> result) {
if (root == null) {
return;
}
result.add(root.val);
traverse(root.left, result);
traverse(root.right, result);
}
}
解法二:借助栈,遍历实现;
本质上跟递归一样,区别是递归使用的是系统栈;
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Stack<TreeNode> st = new Stack<TreeNode>();
TreeNode node = root;
while(node!=null||st.size()>0) {
while(node!=null) {
res.add(node.val);
st.push(node);
node=node.left;
}
if(!st.empty()) {
node=st.pop();
node=node.right;
}
}
return res;
}
}
解法三:
分治;
public class Solution {
public ArrayList<Integer> preorderTraversal(TreeNode root) {
ArrayList<Integer> result = new ArrayList<Integer>();
// null or leaf
if (root == null) {
return result;
}
// Divide
ArrayList<Integer> left = preorderTraversal(root.left);
ArrayList<Integer> right = preorderTraversal(root.right);
// Conquer
result.add(root.val);
result.addAll(left);
result.addAll(right);
return result;
}
}
T-2 二叉搜索树的迭代器
https://leetcode-cn.com/problems/binary-search-tree-iterator/
T-3 二叉树的最大深度
https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/
解法一:
分治法:
public class Solution {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left, right) + 1;
}
}
解法二:遍历
public int maxDepth(TreeNode root) {
if(root==null)
return 0;
Queue<TreeNode> qu = new LinkedList<TreeNode>();
qu.offer(root);
int depth=0;
while(qu.size()>0) {
int size=qu.size();
depth++;
while(size-->0) {
TreeNode node = qu.poll();
if(node.left!=null)
qu.offer(node.left);
if(node.right!=null)
qu.offer(node.right);
}
}
return depth;
}
T-4 判断是否是平衡二叉树
https://leetcode-cn.com/problems/balanced-binary-tree/
技巧:
使用-1代表不平衡;
分治法;
public class Solution {
public boolean isBalanced(TreeNode root) {
return maxDepth(root) != -1;
}
private int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
if (left == -1 || right == -1 || Math.abs(left-right) > 1) {
return -1;
}
return Math.max(left, right) + 1;
}
}
T-5 二叉树的最近公共祖先
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/
分治法:
public class Solution {
// 在root为根的二叉树中找A,B的LCA:
// 如果找到了就返回这个LCA
// 如果只碰到A,就返回A
// 如果只碰到B,就返回B
// 如果都没有,就返回null
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode node1, TreeNode node2) {
if (root == null || root == node1 || root == node2) {
return root;
}
// Divide
TreeNode left = lowestCommonAncestor(root.left, node1, node2);
TreeNode right = lowestCommonAncestor(root.right, node1, node2);
// Conquer
if (left != null && right != null) {
return root;
}
if (left != null) {
return left;
}
if (right != null) {
return right;
}
return null;
}
}
T-6 二叉树中的最大路径和
https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/
public class Solution {
private class ResultType {
// singlePath: 从root往下走到任意点的最大路径,这条路径可以不包含任何点
// maxPath: 从树中任意到任意点的最大路径,这条路径至少包含一个点
int singlePath, maxPath;
ResultType(int singlePath, int maxPath) {
this.singlePath = singlePath;
this.maxPath = maxPath;
}
}
private ResultType helper(TreeNode root) {
if (root == null) {
return new ResultType(0, Integer.MIN_VALUE);
}
// Divide
ResultType left = helper(root.left);
ResultType right = helper(root.right);
// Conquer
int singlePath = Math.max(left.singlePath, right.singlePath) + root.val;
singlePath = Math.max(singlePath, 0);
int maxPath = Math.max(left.maxPath, right.maxPath);
maxPath = Math.max(maxPath, left.singlePath + right.singlePath + root.val);
return new ResultType(singlePath, maxPath);
}
public int maxPathSum(TreeNode root) {
ResultType result = helper(root);
return result.maxPath;
}
}