P6 二叉树
二叉树的结构
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
二叉树的先序、中序、后序遍历
先序遍历
// 递归
List<Integer> res = new ArrayList<>();
public List<Integer> preOrderTraversal(TreeNode root) {
if (root == null) {
return Collections.emptyList();
}
res.add(root.val);
if (root.left != null) {
preOrderTraversal(root.left);
}
if (root.right != null) {
preOrderTraversal(root.right);
}
return res;
}
// 非递归
public List<Integer> preOrderTraversal(TreeNode root) {
if (root == null) {
return Collections.emptyList();
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
TreeNode node = null;
List<Integer> res = new ArrayList<>(101);
while (!stack.isEmpty()) {
node = stack.pop();
res.add(node.val);
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
return res;
}
中序遍历
// 递归
List<Integer> res = new ArrayList<>();
public List<Integer> inOrderTraversal(TreeNode root) {
if (root == null) {
return Collections.emptyList();
}
if (root.left != null) {
inOrderTraversal(root.left);
}
res.add(root.val);
if (root.right != null) {
inOrderTraversal(root.right);
}
return res;
}
// 非递归
public List<Integer> inOrderTraversal(TreeNode root) {
if (root == null) {
return Collections.emptyList();
}
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
if (node != null) {
stack.push(node);
node = node.left;
} else {
node = stack.pop();
res.add(node.val);
node = node.right;
}
}
return res;
}
后序遍历
// 递归
public List<Integer> postOrderTraversal(TreeNode root) {
if (root == null) {
return Collections.emptyList();
}
List<Integer> res = new ArrayList<>(100);
help(root, res);
return res;
}
public void help(TreeNode root, List<Integer> res) {
if (root.left != null) {
help(root.left, res);
}
if (root.right != null) {
help(root.right, res);
}
res.add(root.val);
}
// 非递归
public List<Integer> postOrderTraversal(TreeNode root) {
if (root == null) {
return Collections.emptyList();
}
Stack<TreeNode> stack = new Stack<>();
Stack<Integer> help = new Stack<>();
stack.push(root);
TreeNode node = null;
List<Integer> res = new ArrayList<>(101);
while (!stack.isEmpty()) {
node = stack.pop();
help.push(node.val);
if (node.left != null) {
stack.push(node.left);
}
if (node.right != null) {
stack.push(node.right);
}
}
while (!help.isEmpty()) {
res.add(help.pop());
}
return res;
}
二叉树的宽度优先遍历
public List<Integer> levelOrderTraversal(TreeNode root) {
if (root == null) {
return Collections.emptyList();
}
Queue<TreeNode> queue = new LinkedList<>();
List<Integer> res = new ArrayList<>();
queue.add(root);
TreeNode node = null;
while (!queue.isEmpty()) {
node = queue.poll();
res.add(node.val);
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
return res;
}
判断一棵二叉树是不是搜索二叉树
搜索二叉树
左子树节点都比根节点小,右子树节点都比根节点大
中序遍历判断是否是搜索二叉树
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean isValidBST(TreeNode node, long lower, long upper) {
if (node == null) {
return true;
}
if (node.val <= lower || node.val >= upper) {
return false;
}
return isValidBST(node.left, lower, node.val) && isValidBST(node.right, node.val, upper);
}
判断一棵二叉树是不是完全二叉树
完全二叉树
满二叉树是完全二叉树,如果不是满二叉树,最后一层节点从左到右排列也是完全二叉树
宽度遍历二叉树判断是否完全二叉树
- 任意一个节点,如果只有右子树没有左子树,就不是完全二叉树
- 如果遇到一个不同时拥有两个孩子的节点,之后的节点都是叶子节点,否则就不是完全二叉树
public boolean levelOrderTraversal(TreeNode root) {
if (root == null) {
return Collections.emptyList();
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
TreeNode node = null;
boolean res = true;
boolean leaf = false;
while (!queue.isEmpty()) {
node = queue.poll();
if(!leaf && node.left == null && node.right == null) {
leaf = true;
}
if(leaf && (node.left != null || node.right != null)) {
res = false;
}
if(node.left == null && node.right != null) {
res = false;
}
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
return res;
}
判断一棵二叉树是不是满二叉树
满二叉树
每一层节点都是满的二叉树是满二叉树
最大深度和节点个数判断是不是满二叉树
节点个数是 N,深度是 h,两者满足 就是满二叉树
public boolean fullTree(TreeNode root) {
int h = dfs(root);
int n = leafs(root);
return n == ((2 << (h - 1)) - 1);
}
public int leafs(TreeNode root) {
if(root == null) {
return 0;
}
return leafs(root.left) + leafs(root.right) + 1;
}
public int dfs(TreeNode root, int depth) {
if(root == null) {
return 0;
}
return Math.max(dfs(root.left), dfs(root.right)) + 1;
}
判断一棵二叉树是不是平衡二叉树
平衡二叉树
对于每一个节点,左子树和右子树深度之差不超过1
递归求解是不是平衡二叉树
static class ReturnType {
int depth;
boolean isBalanced;
ReturnType(int depth, boolean isBalanced) {
this.depth = depth;
this.isBalanced = isBalanced;
}
}
public boolean isBalanced(TreeNode root) {
return isBalanced2(root).isBalanced;
}
public ReturnType isBalanced2(TreeNode root) {
if (root == null) {
return new ReturnType(0, true);
}
ReturnType l = isBalanced2(root.left);
ReturnType r = isBalanced2(root.right);
boolean isBalanced = l.isBalanced && r.isBalanced && Math.abs(l.depth - r.depth) <= 1;
int depth = Math.max(l.depth, r.depth) + 1;
return new ReturnType(depth, isBalanced);
}
最低公共祖节点
给定两个二叉树节点 node1 和 node2,找到它们的最低公共祖节点
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return null;
} else if (root == p) {
return p;
} else if (root == q) {
return q;
}
TreeNode lRes = lowestCommonAncestor(root.left, p, q);
TreeNode rRes = lowestCommonAncestor(root.right, p, q);
if (lRes != null && rRes != null) {
return root;
} else if (lRes == null && rRes == null) {
return null;
} else if (lRes != null) {
return lRes;
} else {
return rRes;
}
}
在二叉树中找到一个节点的后继节点
后继节点:中序遍历之后节点后面的那个节点
前驱节点:中序遍历之后节点前面的那个节点
public TreeNode nextNode(TreeNode root, TreeNode node) {
TreeNode nextNode = null;
Stack<TreeNode> stack = new Stack<>();
TreeNode p = root;
while(p != null || !stack.isEmpty()) {
if(p ! = null) {
stack.push(p);
p = p.left;
} else{
p = stack.pop();
if(p == node) {
if(!stack.isEmpty()) {
nextNode = stack.pop();
} else {
nextNode = node.right;
}
break;
}
}
}
return nextNode;
}
二叉树的序列化和反序列化
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
return serialize(root, new StringBuffer("")).toString();
}
public StringBuffer serialize(TreeNode root, StringBuffer sb) {
if (root == null) {
sb.append("#,");
} else {
sb.append(String.valueOf(root.val)).append(",");
sb = serialize(root.left, sb);
sb = serialize(root.right, sb);
}
return sb;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
List<String> list = new LinkedList<>(Arrays.asList(data.split(",")));
return deserialize(list);
}
public TreeNode deserialize(List<String> list) {
if (list.get(0).equals("#")) {
list.remove(0);
return null;
}
TreeNode root = new TreeNode(Integer.parseInt(list.get(0)));
list.remove(0);
root.left = deserialize(list);
root.right = deserialize(list);
return root;
}
判断一棵二叉树是不是另一棵二叉树的子树
private boolean isSame(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) {
return true;
}
if (t1 == null || t2 == null) {
return false;
}
return t1.val == t2.val && isSame(t1.left, t2.left) && isSame(t1.right, t2.right);
}
public boolean checkSubTree(TreeNode t1, TreeNode t2) {
if (t1 == null) {
return t2 == null;
}
return isSame(t1, t2) || checkSubTree(t1.left, t2) || checkSubTree(t1.right, t2);
}