对于二叉树的题目来说,无非就是递归左右子树,需要注意的是自顶向下还是自下而上!
1、中序遍历二叉树
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
// 递归
List<Integer> list = new LinkedList<>();
dfs(root, list);
return list;
void dfs(TreeNode cur, List<Integer> list) {
if (cur == null) return;
dfs(cur.left, list);
list.add(cur.val);
dfs(cur.right, list);
}
// 非递归
List<Integer> list = new ArrayList<>();
if (root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
if (cur != null) {
stack.push(cur);
cur = cur.left;
} else {
cur = stack.pop();
list.add(cur.val);
cur = cur.right;
}
}
return list;
}
}
2、相同的树
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
} else if (p != null & q == null) {
return false;
} else if (p == null & q != null) {
return false;
}
if (p.val == q.val && isSameTree(p.left, q.left) && isSameTree(p.right, q.right)) {
return true;
}
return false;
}
}
3、对称二叉树
class Solution {
public boolean isSymmetric(TreeNode root) {
return traverse(root.left, root.right);
}
boolean traverse(TreeNode a, TreeNode b) {
if (a == null && b == null) {
return true;
} else if (a != null && b == null) {
return false;
} else if (a == null && b != null) {
return false;
}
if (a.val == b.val && traverse(a.left, b.right) && traverse(a.right, b.left)) {
return true;
}
return false;
}
}
4、二叉树的最大深度
class Solution {
int max = 0;
public int maxDepth(TreeNode root) {
traverse(root, 0);
return max;
}
int traverse(TreeNode root, int depth) {
if (root == null) return depth;
depth++;
if (depth > max) {
max = depth;
}
traverse(root.left, depth);
traverse(root.right, depth);
return depth;
}
}
5、将有序数组转换为二叉搜索树
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return traverse(nums, 0, nums.length-1);
}
TreeNode traverse(int[] nums, int left, int right) {
if (left > right) return null;
int mid = (left + right) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = traverse(nums, left, mid-1);
root.right = traverse(nums, mid+1, right);
return root;
}
}
6、平衡二叉树
class Solution {
boolean flag = true;
public boolean isBalanced(TreeNode root) {
int res = traverse(root);
if (res > -1) {
return true;
}
return false;
}
int traverse(TreeNode root) {
if (root == null) {
return 0;
}
int l = traverse(root.left);
int r = traverse(root.right);
if (l == -1 || r == -1 || Math.abs(l-r) > 1) {
return -1;
} else {
return Math.max(l, r) + 1;
}
}
}
7、二叉树的最小深度
class Solution {
public int minDepth(TreeNode root) {
return minL(root);
}
int minL(TreeNode root) {
if (root == null) return 0;
int l = minL(root.left);
int r = minL(root.right);
if (l == 0) {
return r + 1;
} else if (r == 0) {
return l + 1;
}
return Math.min(l, r) + 1;
}
}
8、路径总和
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) {
return false;
}
if (root.left == null && root.right == null) {
return sum == root.val;
}
return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}
}
9、二叉树的前序遍历
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
return list;
}
void dfs (TreeNode cur, List<Integer> list) {
if (cur == null) return;
list.add(cur.val);
dfs(cur.left, list);
dfs(cur.right, list);
}
}
10、二叉树的后序遍历
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
dfs(root, list);
return list;
}
void dfs(TreeNode node, List<Integer> list) {
if (node == null) return;
dfs(node.left, list);
dfs(node.right, list);
list.add(node.val);
}
}
11、翻转二叉树
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
TreeNode left = invertTree(root.left);
TreeNode right = invertTree(root.right);
root.left = right;
root.right = left;
return root;
}
}
12、二叉搜索树的最近公共祖先
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) return null;
if (root == p || root == q) return root;
TreeNode left = null;
TreeNode right = null;
if (p.val > root.val && q.val > root.val) {
right = lowestCommonAncestor(root.right, p, q);
} else if (p.val < root.val && q.val > root.val) {
left = lowestCommonAncestor(root.left, p, q);
right = lowestCommonAncestor(root.right, p, q);
} else if (q.val < root.val && p.val > root.val) {
left = lowestCommonAncestor(root.left, p, q);
right = lowestCommonAncestor(root.right, p, q);
} else if (p.val < root.val && q.val < root.val) {
left = lowestCommonAncestor(root.left, p, q);
}
if (left != null && right != null) return root;
if (left != null && right == null) return left;
if (left == null && right != null) return right;
if (left == null && right == null) return null;
return null;
}
}
13、二叉树的所有路径
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList<>();
getPath(root, "", res);
return res;
}
void getPath(TreeNode root, String path, List<String> paths) {
if (root != null) {
path += root.val;
if (root.left == null && root.right == null) {
paths.add(path);
} else if (root.left != null || root.right != null) {
path += "->";
getPath(root.left, path, paths);
getPath(root.right, path, paths);
}
}
}
}
14、左叶子之和
// 需要注意的是,这里是左叶子之和不是左节点!!
class Solution {
private int sum;
public int sumOfLeftLeaves(TreeNode root) {
sum = 0;
traverse(root);
return sum;
}
void traverse(TreeNode root) {
if (root == null) return;
if (root.left != null && root.left.left == null && root.left.right == null) {
sum += root.left.val;
}
traverse(root.left);
traverse(root.right);
}
}
15、二叉树的坡度
需要注意审题,这里是左右子树之和的差
class Solution {
int sum = 0;
public int findTilt(TreeNode root) {
traverse(root);
return sum;
}
int traverse(TreeNode root) {
if (root == null) return 0;
int left = traverse(root.left);
int right = traverse(root.right);
sum += Math.abs(left - right);
return root.val + left + right;
}
}
16、二叉搜索树中的众数
class Solution {
List<Integer> res = new LinkedList<>();
int max = 0;
int tempMax = 0;
TreeNode pre = null;
public int[] findMode(TreeNode root) {
traverse(root);
int[] arr = res.stream().mapToInt(Integer::intValue).toArray();
return arr;
}
void traverse(TreeNode root) {
if (root == null) return;
traverse(root.left);
if (pre != null && root.val == pre.val) {
tempMax++;
} else {
tempMax = 1;
}
if (tempMax == max){
res.add(root.val);
} else if (tempMax > max) {
res.clear();
max = tempMax;
res.add(root.val);
}
pre = root;
traverse(root.right);
}
}
17、二叉搜索树的最小绝对差
class Solution {
private TreeNode pre = null;
int min = 0;
boolean flag = false; // 判断是否初始化了min
public int getMinimumDifference(TreeNode root) {
traverse(root);
return min;
}
void traverse(TreeNode cur) {
if (cur == null) return;
traverse(cur.left);
if (pre == null) {
pre = cur;
} else if (!flag) {
flag = true;
min = Math.abs(cur.val - pre.val);
} else if (flag && Math.abs(cur.val-pre.val) < min) {
min = Math.abs(cur.val - pre.val);
}
pre = cur;
traverse(cur.right);
}
}
18、二叉树的直径
class Solution {
int ans;
public int diameterOfBinaryTree(TreeNode root) {
ans = 1;
depth(root);
return ans - 1;
}
public int depth(TreeNode node) {
if (node == null) {
return 0; // 访问到空节点了,返回0
}
int L = depth(node.left); // 左儿子为根的子树的深度
int R = depth(node.right); // 右儿子为根的子树的深度
ans = Math.max(ans, L+R+1); // 计算d_node即L+R+1 并更新ans
return Math.max(L, R) + 1; // 返回该节点为根的子树的深度
}
}
19、另一颗树的子树(此题有哈希解法)
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
return dfs(s, t);
}
public boolean dfs(TreeNode s, TreeNode t) {
if (s == null) {
return false;
}
return check(s, t) || dfs(s.left, t) || dfs(s.right, t);
}
public boolean check(TreeNode s, TreeNode t) {
if (s == null && t == null) {
return true;
}
if (s == null || t == null || s.val != t.val) {
return false;
}
return check(s.left, t.left) && check(s.right, t.right);
}
}
哈希
class Solution {
static final int MAX_N = 1005;
static final int MOD = 1000000007;
boolean[] vis = new boolean[MAX_N];
int[] p = new int[MAX_N];
int tot;
Map<TreeNode, int[]> hS = new HashMap<TreeNode, int[]>();
Map<TreeNode, int[]> hT = new HashMap<TreeNode, int[]>();
public boolean isSubtree(TreeNode s, TreeNode t) {
getPrime();
dfs(s, hS);
dfs(t, hT);
int tHash = hT.get(t)[0];
for (Map.Entry<TreeNode, int[]> entry : hS.entrySet()) {
if (entry.getValue()[0] == tHash) {
return true;
}
}
return false;
}
public void getPrime() {
vis[0] = vis[1] = true;
tot = 0;
for (int i = 2; i < MAX_N; ++i) {
if (!vis[i]) {
p[++tot] = i;
}
for (int j = 1; j <= tot && i * p[j] < MAX_N; ++j) {
vis[i * p[j]] = true;
if (i % p[j] == 0) {
break;
}
}
}
}
public void dfs(TreeNode o, Map<TreeNode, int[]> h) {
h.put(o, new int[]{o.val, 1});
if (o.left == null && o.right == null) {
return;
}
if (o.left != null) {
dfs(o.left, h);
int[] val = h.get(o);
val[1] += h.get(o.left)[1];
val[0] = (int) ((val[0] + (31L * h.get(o.left)[0] * p[h.get(o.left)[1]]) % MOD) % MOD);
}
if (o.right != null) {
dfs(o.right, h);
int[] val = h.get(o);
val[1] += h.get(o.right)[1];
val[0] = (int) ((val[0] + (179L * h.get(o.right)[0] * p[h.get(o.right)[1]]) % MOD) % MOD);
}
}
}
20、根据二叉树创建字符串
这题主要是吓唬人,看清题意就行。
class Solution {
public String tree2str(TreeNode root) {
return dfs(root);
}
String dfs(TreeNode root) {
if (root == null) return "-";
String left = dfs(root.left);
String right = dfs(root.right);
if (left.equals("-") && right.equals("-")) {
return root.val + "";
} else if (!left.equals("-") && right.equals("-")) {
return root.val + "(" + left + ")";
} else if (left.equals("-") && !right.equals("-")) {
return root.val + "()" + "(" + right+ ")";
} else if (!left.equals("-") && !right.equals("-")) {
return root.val + "(" + left + ")" + "(" + right +")";
}
return "-";
}
}
21、合并二叉树
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if (root1 == null) {
return root2;
}
if (root2 == null) {
return root1;
}
TreeNode merged = new TreeNode(root1.val + root2.val);
merged.left = mergeTrees(root1.left, root2.left);
merged.right = mergeTrees(root1.right, root2.right);
return merged;
}
}