1.二叉树最大深度(104-易)
题目描述:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
思路:实现简单,直接使用递归和迭代求解。
代码实现:
// 递归
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> queue = new LinkedList<>();
queue.add(root);
int level = 0;
while (!queue.isEmpty()) {
int size = queue.size();
++level;
for (int i = 0; i < size; ++i) {
// 遍历本层,移除一个节点,并加入下一层对应的子节点
TreeNode node = queue.poll();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
}
return level;
}
2.平衡二叉树(110-易)
题目描述:给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
示例:
输入:root = [3,9,20,null,null,15,7]
输出:true
思路:
- 递归(自顶向下):递归最大深度,注意:我们要保证每颗子树都是平衡二叉树,所有主函数也要递归。
- 递归(自底向上):在递归最大深度的是够进行判断,即只要子树出现不满足平衡二叉树的要求,直接返回false,推荐。
代码实现:
// 递归(自顶向下)
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
return Math.abs(dfs(root.left) - dfs(root.right)) < 2
&& isBalanced(root.left)
&& isBalanced(root.right);
}
private int dfs(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(dfs(root.left), dfs(root.right)) + 1;
}
// 递归(自底向上)
private boolean ans = true;
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
dfs(root);
return ans;
}
private int dfs(TreeNode root) {
if (root == null) {
return 0;
}
int left = dfs(root.left);
int right = dfs(root.right);
if (Math.abs(left - right) > 1) {
ans = false;
}
return Math.max(left, right) + 1;
}
3.二叉树最小深度(111-易)
题目描述:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
示例:
输入:root = [3,9,20,null,null,15,7]
输出:2
思路:
- 递归:与求深度相同(最大深度),但这里递归函数为根节点到叶子节点的最小深度。当只有一颗子树的情况,计算深度(基本逻辑)
- 迭代:迭代遍历层数就是我们的深度,只要在某层出现叶子节点,我们就返回层数(深度)。
代码实现:
// 递归
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
int left = minDepth(root.left);
int right = minDepth(root.right);
if (root.left == null || root.right == null) {
return left + right + 1;
}
return Math.min(left, right) + 1;
}
// 迭代
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int level = 0;
while (!queue.isEmpty()) {
int size = queue.size();
++level;
for (int i = 0; i < size; ++i) {
TreeNode node = queue.poll();
if (node.left == null && node.right == null) {
return level;
}
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
}
return 0;
}
总结:这种题目比较简单,其实深度延伸的题目还有很多,比如二叉树的直径(543),这种问题的都是根节点到叶子节点的问题。对于这种问题,有时自下向上的递归也是不错的选择
4.二叉树右视图(199-中)
题目描述:给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例:
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:
1 <---
/ \
2 3 <---
\ \
5 4 <---
思路:使用广度优先搜索,只需要记录每一层的最后一个元素即可,左视图同理。
代码实现:
public List<Integer> rightSideView(TreeNode root) {
List<Integer> ans = new ArrayList<>();
if (root == null) {
return ans;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; ++i) {
TreeNode node = queue.poll();
if (i == size - 1) {
ans.add(node.val);
}
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
}
return ans;
}
延伸:T513找二叉树左下角的值,返回数组最后一个值即可。提供一个递归思路:
private int max = -1; //记录最大层数
private int res = 0;
public int findBottomLeftValue(TreeNode root) {
dfs(root, 0);
return res;
}
private void dfs (TreeNode node, int level) {
if (node == null) return;
//递归层第一次大于当前最大层,即每层的第一个节点(更新)
if (level > max) {
max = level;
res = node.val;
}
dfs(node.left, level + 1);
dfs(node.right, level + 1);
}
5.二叉树每行的最大值(515-中)
题目描述:您需要在二叉树的每一行中找到最大的值。
示例:
输入:
1
/ \
3 2
/ \ \
5 3 9
输出: [1, 3, 9]
思路:迭代实现比较简单,加一个变量更新每层的最大值即可。注意:确定完一层的最大值之后,不要忘记将max设置为最小值。
代码实现:
public List<Integer> largestValues(TreeNode root) {
if (root == null) {
return new ArrayList<>();
}
List<Integer> ans = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int max = Integer.MIN_VALUE;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; ++i) {
TreeNode node = queue.poll();
max = Math.max(max, node.val);
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
ans.add(max);
max = Integer.MIN_VALUE;
}
return ans;
}
补充一个DFS解法,我们在递归的过程将每层的最大值进行设置更新,代码实现:
public List<Integer> largestValues(TreeNode root) {
List<Integer> result = new ArrayList<>();
//层级从0开始,result不需要考虑加1、减1的情况
dfs(root,0,result);
return result;
}
public void dfs(TreeNode root, int level, List<Integer> result) {
if (root == null) {
return;
}
if (result.size() == level) {
result.add(level , root.val);
}
int max = Math.max(result.get(level), root.val);
result.set(level, max);
dfs(root.left, level + 1, result);
dfs(root.right, level + 1, result);
}
补充:二叉搜索树的最小绝对值(T530),由于二叉搜索树中序遍历的有序性,所以最小值一定出现在中序遍历的相邻位置。可以使用递归和迭代求解。
代码实现:
// 递归
private TreeNode pre = null;
private int min = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
inorder(root);
return min;
}
private void inorder(TreeNode root) {
if (root == null) {
return;
}
inorder(root.left);
if (pre != null) {
min = Math.min(min, root.val - pre.val);
}
pre = root;
inorder(root.right);
}
// 迭代
public int getMinimumDifference(TreeNode root) {
if (root == null) {
return 0;
}
TreeNode pre = null;
int min = Integer.MAX_VALUE;
Deque<TreeNode> stack = new LinkedList<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
TreeNode node = stack.pop();
if (pre != null) {
min = Math.min(min, node.val - pre.val);
}
pre = node;
cur = node.right;
}
return min;
}
网友评论