递归算法
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
在使用递归算法求得二叉树的最小深度时与求最大深度的思路类似,代码如下
public int minDepth(TreeNode root) {
if (root == null) return 0;
return Math.min(minDepth(root.left), minDepth(root.right)) + 1;
}
那么代码是不是就这样呢?这样写看起来是对的,但其实这种解法忽略了一种情况,就是说,如果一个节点只有左子树,没有右子树,那么从这个节点开始的最小深度究竟是1还是左子树的深度呢,从上面这种算法来看,求出来等于1
类似于这种二叉树,它的最小深度是3,而不是1,那么该如何改进呢?
public int minDepth(TreeNode root) {
if (root == null) return 0;
/*
当一个节点的左节点为null或者右节点为null时
返回的并不是较小值,而是较大值,因为当前节点不是叶子节点,返回的是不为null节点的最小深度
*/
if (root.left == null || root.right == null) {
return Math.max(minDepth(root.left), minDepth(root.right)) + 1;
}
// 当节点的左右节点都存在时,则返回左右子树深度的较小值+1
return Math.min(minDepth(root.left), minDepth(root.right)) + 1;
}
非递归算法(BFS)
同样是使用使用广度遍历,依次将所有节点一次加入到队列中,每遍历完一层深度++
public int minDepth(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
int count = 0;
if (root == null) {
return 0;
}
// 将根节点和一个标志null加入到队列中
queue.offer(root);
queue.offer(null);
while (!queue.isEmpty()) {
root = queue.poll();
// 如果是null则表示一层已经遍历完,深度++
if (root == null) {
// 如果队列已经是空了,则不需要加入null
if (!queue.isEmpty()) {
queue.offer(null);
}
count++;
} else {
if (root.left != null) {
queue.offer(root.left);
}
if (root.right != null) {
queue.offer(root.right);
}
// 如果当前节点的左右节点都不存在则说明这个节点时距离根节点最近的叶子结点,即可退出循环
if (root.left == null && root.right == null) {
count++;
break;
}
}
}
return count;
}
为什么队列操作不使用add和remove,而使用offer和poll呢?
- add和offer都是添加一个元素,不同之处在于,如果超出队列的界限时,add会抛出一个异常,而offer会返回false
- remove和poll都是从链表首抽取一个元素,区别在如果链表为空时remove会抛出一个异常,而poll则是返回一个null