【小嘟陪你刷题14】二叉树的最小深度、二叉树的所有路径、翻转二叉树
创始人
2024-03-31 22:13:00
0

目录

  • 一、二叉树的最小深度
    • 思路一:深度优先搜索
    • 代码实现
    • 思路二:广度优先搜索
    • 代码实现
  • 二、二叉树的所有路径
    • 思路一:递归法
    • 代码实现
    • 思路二:迭代法
  • 三、翻转二叉树
    • 思路一:递归法
    • 代码实现
    • 思路二:迭代法
    • 代码实现

一、二叉树的最小深度

在这里插入图片描述

思路一:深度优先搜索

我们这里使用后序遍历的方式!
对于每一个非叶子节点,我们只需要分别计算其左右子树的最小叶子节点的深度,就将大问题转化成小问题。
确定终止条件
终止条件也是遇到空节点返回0,表示当前节点的高度为0.

if (root == null) return 0;

确定单层递归的逻辑
这块和求最大深度不一样,会写出如下代码:

int leftDepth = minDepth(root.left);
int rightDepth = minDepth(root.right);
int result = 1 + Math.min(leftDepth, rightDepth);
return result;

这个代码就犯了此图中的误区:

在这里插入图片描述
如果这样求,没有左孩子的分支会算为最短深度。
所以,如果左子树为空,右子树不为空,说明最小速度为1 + 右子树的深度。
反之,异然。
最后如果左子树右子树都不为空,返回最小值+1;

代码实现

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public int minDepth(TreeNode root) {if (root == null) return 0;if (root.left == null && root.right == null) {return 1;}int result = 0;int leftDepth = minDepth(root.left);int rightDepth = minDepth(root.right);if (root.left == null || root.right == null) return leftDepth + rightDepth + 1;result = Math.min(leftDepth, rightDepth) + 1;return result;}
}

在这里插入图片描述

思路二:广度优先搜索

本题还可以使用层序遍历的方法来解决,思路是一样的。
需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点。

代码实现

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public int minDepth(TreeNode root) {if (root == null) {return 0;}Deque deque = new LinkedList<>();deque.offer(root);int depth = 0;while (!deque.isEmpty()) {int size = deque.size();depth++;for (int i = 0; i < size; i++) {TreeNode poll = deque.poll();if (poll.left == null && poll.right == null) {return depth;}if (poll.left != null) {deque.offer(poll.left);}if (poll.right != null) {deque.offer(poll.right);}}}return depth;}
}

在这里插入图片描述

二、二叉树的所有路径

在这里插入图片描述

思路一:递归法

我们使用前序遍历的方法!
在这里插入图片描述
确定递归终止条件
在写递归的时候我们习惯了这么写:

if (root == null) {终止处理逻辑
}

但是本题的终止条件这样写会很麻烦,因为本题要找到叶子节点,就开始结束的处理逻辑了(把路径放进result里)。

那么什么时候算是找到了叶子节点? 是当 cur不为空,其左右孩子都为空的时候,就找到叶子节点。

if (root.left == null && root.right == null) {
}

为什么没有判断cur是否为空呢?因为下面的逻辑可以控制空节点不入循环。

我们使用List结构path来记录路径,所以要把List结构的path转为String格式,再把这个String放进result里。

为什么要是有List?因为在下面处理单层递归逻辑的时候,要做回溯,使用List方便回溯。

确定单层递归逻辑
因为是前序遍历,需要先处理中间节点,中间节点就是我们要记录路劲上的节点,先放进path中。
然后是递归和回溯的过程。上面说过没有判断root是否为空,那么在这里递归的时候,如果为空就不进行下一层递归了。所以递归前要加上判断语句,下面要递归的节点是否为空。
递归完,要做回溯啊,因为path 不能一直加入节点,它还要删节点,然后才能加入新的节点。
回溯和递归是一一对应的,有一个递归,就要有一个回溯,这么写的话相当于把递归和回溯拆开了, 一个在花括号里,一个在花括号外。

所以回溯要和递归永远在一起,世界上最遥远的距离是你在花括号里,而我在花括号外!

代码实现

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public List binaryTreePaths(TreeNode root) {List res = new ArrayList<>();if (root == null) {return res;}List paths = new ArrayList<>();traversal(root, paths, res);return res;}private void traversal(TreeNode root, List paths, List res) {paths.add(root.val);// 叶子结点if (root.left == null && root.right == null) {// 输出StringBuilder sb = new StringBuilder();for (int i = 0; i < paths.size() - 1; i++) {sb.append(paths.get(i)).append("->");}sb.append(paths.get(paths.size() - 1));res.add(sb.toString());return;}if (root.left != null) {traversal(root.left, paths, res);paths.remove(paths.size() - 1);// 回溯}if (root.right != null) {traversal(root.right, paths, res);paths.remove(paths.size() - 1);// 回溯}}
}

在这里插入图片描述

思路二:迭代法

至于非递归的方式,我们可以依然可以使用前序遍历的迭代方式来模拟遍历路径的过程,这里除了模拟递归需要一个栈,同时还需要一个栈来存放对应的遍历路径。

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public List binaryTreePaths(TreeNode root) {List result = new ArrayList<>();if (root == null)return result;Stack stack = new Stack<>();// 节点和路径同时入栈stack.push(root);stack.push(root.val + "");while (!stack.isEmpty()) {// 节点和路径同时出栈String path = (String) stack.pop();TreeNode node = (TreeNode) stack.pop();// 若找到叶子节点if (node.left == null && node.right == null) {result.add(path);}//右子节点不为空if (node.right != null) {stack.push(node.right);stack.push(path + "->" + node.right.val);}//左子节点不为空if (node.left != null) {stack.push(node.left);stack.push(path + "->" + node.left.val);}}return result;}
}
 

在这里插入图片描述

三、翻转二叉树

在这里插入图片描述

思路一:递归法

在这里插入图片描述
确定终止条件
当前节点为空的时候,就返回

if (root == null) return root;

确定单层递归的逻辑
因为是先前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。

swap(root.left, root.right);
invertTree(root.left);
invertTree(root.right);

代码实现

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public TreeNode invertTree(TreeNode root) {if (root == null) {return null;}invertTree(root.left);invertTree(root.right);swapChildren(root);return root;}private void swapChildren(TreeNode root) {TreeNode tmp = root.left;root.left = root.right;root.right = tmp;}
}

在这里插入图片描述

思路二:迭代法

代码实现

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public TreeNode invertTree(TreeNode root) {if (root == null) {return null;}ArrayDeque deque = new ArrayDeque<>();deque.offer(root);while (!deque.isEmpty()) {int size = deque.size();while (size-- > 0) {TreeNode node = deque.poll();swap(node);if (node.left != null) {deque.offer(node.left);}if (node.right != null) {deque.offer(node.right);}}}return root;}public void swap(TreeNode root) {TreeNode temp = root.left;root.left = root.right;root.right = temp;}
}

在这里插入图片描述

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...