1、验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isValidBST(TreeNode root) {
return dfs(root, Integer.MAX_VALUE, Integer.MIN_VALUE);
}
public boolean dfs(TreeNode root, long max, long min) {
if (root == null) return true;
if (root.val > max || root.val < min) return false;
return dfs(root.left, root.val - 1L, min) && dfs(root.right, max, root.val + 1L);
}
}
这里为什么用long类型的参数呢?
因为当节点root.val为Integer.MIN_VALUE时,然后执行-1操作会溢出。
测试数据存在:[-2147483648,-2147483648]
2、二叉树的中序遍历
给定一个二叉树,返回它的中序遍历。
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
1、递归版
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
ArrayList<Integer> list = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if (root == null) return list;
inorder(root);
return list;
}
public void inorder(TreeNode root) {
if (root == null) return ;
inorder(root.left);
list.add(root.val);
inorder(root.right);
}
}
2、迭代版(栈数据结构)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public ArrayList<Integer> list = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
while (true) {
goAlongLeftBranch(root, stack);
if (stack.isEmpty()) break;
root = stack.pop();
list.add(root.val);
root = root.right;
}
return list;
}
public void goAlongLeftBranch(TreeNode x, Stack s) {
while (x != null) {
s.push(x);
x = x.left;
}
}
}
或者合并起来
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public ArrayList<Integer> list = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
list.add(root.val);
root = root.right;
}
return list;
}
}
3、对称二叉树
给定一个二叉树,检查它是否是镜像对称的。
1
/ \
2 2
/ \ / \
3 4 4 3
进阶:
你可以运用递归和迭代两种方法解决这个问题吗?
1、递归法
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
//递归法
if (root == null) return true;
return dfs(root.left, root.right);
}
public boolean dfs(TreeNode left, TreeNode right) {
if (left == null && right == null) return true;
if (left == null || right == null || left.val != right.val) return false;
return dfs(left.left, right.right) && dfs(left.right, right.left);
}
}
2、迭代版
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) return true;
//迭代版
Stack<TreeNode> left = new Stack<>();
Stack<TreeNode> right = new Stack<>();
TreeNode l = root.left, r = root.right;
while (l != null || r != null || !left.isEmpty() || !right.isEmpty()) {
while (l != null && r != null) {
left.push(l);
l = l.left;
right.push(r);
r = r.right;
}
if (l != null || r != null) return false;
//如果两边是对称的,那么l和r都是null,如果有一边不为null则不对称
l = left.pop();
r = right.pop();
if (l.val != r.val) return false;
l = l.right;
r = r.left;
}
return true;
}
}
4、从前序与中序遍历序列重建二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int[] preorder;
public int[] inorder;
public HashMap<Integer,Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
this.inorder = inorder;
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
//记录中序遍历根元素所在索引,以便将中序遍历序列一份为二
}
return dfs(0, preorder.length - 1, 0, inorder.length - 1);
}
public TreeNode dfs(int pl, int pr, int il, int ir) {
if (pl > pr) return null;
int rootVal = preorder[pl];
TreeNode root = new TreeNode(rootVal);
int k = map.get(rootVal);
//k索引为root节点在中序遍历中的位置
root.left = dfs(pl + 1, pl + k - il, il, k - 1);
root.right = dfs(pl + k - il + 1, pr, k + 1, ir);
return root;
}
}
5、二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
if (root == null) return res;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
LinkedList<Integer> list = new LinkedList<>();
for (int i = 0; i < size; i++) {
TreeNode cur = queue.poll();
list.add(cur.val);
if (cur.left != null) queue.offer(cur.left);
if (cur.right != null) queue.offer(cur.right);
}
res.add(list);
}
return res;
}
}