目录
搜索与回溯算法
1 二叉树的深度
剑指 Offer 55 - I. 二叉树的深度https://leetcode-cn.com/problems/er-cha-shu-de-shen-du-lcof/
1. DFS
class Solution {
int depth = 0;
int res = Integer.MIN_VALUE;
public int maxDepth(TreeNode root) {
if(root == null) return 0;
depth++;
maxDepth(root.left);
res = Math.max(depth, res);
maxDepth(root.right);
depth--;
return res;
}
}
1.2 递归改进(DFS)
class Solution {
public int maxDepth(TreeNode root) {
if(root == null)
return 0;
else
return Math.max(maxDepth(root.left), maxDepth(root.right))+1;
}
}
复杂度分析:
- 时间复杂度 O(N) : N 为树的节点数量,计算树的深度需要遍历所有节点。
- 空间复杂度 O(N) : 最差情况下(当树退化为链表时),递归深度可达到 N 。
2. BFS
-
树的层序遍历 / 广度优先搜索往往利用 队列 实现。
-
关键点: 每遍历一层,则计数器 +1+1 ,直到遍历完成,则可得到树的深度。
class Solution {
public int maxDepth(TreeNode root) {
if(root == null) return 0;
List<TreeNode> queue = new LinkedList<TreeNode>() {{ add(root); }}, tmp;
int res = 0;
while(!queue.isEmpty()) {
tmp = new LinkedList<>();
for(TreeNode node : queue) {
if(node.left != null) tmp.add(node.left);
if(node.right != null) tmp.add(node.right);
}
queue = tmp;
res++;
}
return res;
}
}
复杂度分析:
- 时间复杂度 O(N): N 为树的节点数量,计算树的深度需要遍历所有节点。
- 空间复杂度 O(N): 最差情况下(当树平衡时),队列
queue
同时存储 N/2 个节点。
2 平衡二叉树的深度
剑指 Offer 55 - II. 平衡二叉树https://leetcode-cn.com/problems/ping-heng-er-cha-shu-lcof/
1. 自顶向下的递归
定义函数 height,用于计算二叉树中的任意一个节点的高度.
判断二叉树是否平衡。具体做法类似于二叉树的前序遍历,即对于当前遍历到的节点,首先计算左右子树的高度,如果左右子树的高度差是否不超过 1,再分别递归地遍历左右子节点,并判断左子树和右子树是否平衡。这是一个自顶向下的递归的过程。
class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
} else {
return Math.abs(height(root.left) - height(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);
}
}
public int height(TreeNode root) {
if(root == null)
return 0;
else
return Math.max(height(root.left), height(root.right))+1;
}
}
2. 自底向上的递归
方法一由于是自顶向下递归,因此对于同一个节点,函数 height 会被重复调用,导致时间复杂度较高。如果使用自底向上的做法,则对于每个节点,函数 \texttt{height}height 只会被调用一次。
自底向上递归的做法类似于后序遍历,对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡。如果一棵子树是平衡的,则返回其高度(高度一定是非负整数),否则返回 -1−1。如果存在一棵子树不平衡,则整个二叉树一定不平衡。
class Solution {
public boolean isBalanced(TreeNode root) {
return height(root) >= 0;
}
public int height(TreeNode root) {
if (root == null) {
return 0;
}
int leftHeight = height(root.left);
int rightHeight = height(root.right);
if (leftHeight == -1 || rightHeight == -1 || Math.abs(leftHeight - rightHeight) > 1) {
return -1;
} else {
return Math.max(leftHeight, rightHeight) + 1;
}
}
}
复杂度分析
-
时间复杂度:O(n),其中 n 是二叉树中的节点个数。使用自底向上的递归,每个节点的计算高度和判断是否平衡都只需要处理一次,最坏情况下需要遍历二叉树中的所有节点,因此时间复杂度是 O(n)。
-
空间复杂度:O(n),其中 n 是二叉树中的节点个数。空间复杂度主要取决于递归调用的层数,递归调用的层数不会超过 n。