LeetCode 226 翻转二叉树
思路
反转每个节点的左右子节点。 考虑层序遍历,当每个节点被处理的时候,反转它的左右子节点,再把非空子节点入队。 且本题不需要区分不同的层,所以无需记录每层的节点数量,只要队列不为空,就可以医治循环处理节点。 考虑递归遍历,前后序遍历都是可以的,但中序遍历不方便实现,因为会把某一子树重复反转。
- 确定递归函数的参数和返回值: 参数:树根节点 返回值:空
- 确定结束条件:根节点为空或叶子节点可以返回
- 确定单层递归逻辑:反转左右子节点,再分别对左右子节点递归调用
解法(层序遍历)
class Solution {
public TreeNode invertTree(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
if (root != null) {
queue.offer(root);
}
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
// 交换左右子节点
TreeNode tmp = node.left;
node.left = node.right;
node.right = tmp;
// 左右子节点入队
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
return root;
}
}
解法(前序遍历)
class Solution {
public TreeNode invertTree(TreeNode root) {
traverse(root);
return root;
}
public void traverse(TreeNode root) {
if (root == null || (root.left == null && root.right == null)) {
return ;
}
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
traverse(root.left);
traverse(root.right);
}
}
LeetCode 101 对称二叉树
思路
考虑对称二叉树的结构,可以发现根节点的左右子树是镜像的。也就是说,如果对左子树用左中右的顺序遍历,而右子树用右中左的顺序遍历,得到的结果应该是一样的。 所以我们可以如下设计一个递归函数:
- 递归函数的参数和返回值: 参数:左子树的根节点root1和右子树的根节点root2 返回值:布尔类型
- 递归结束条件:
- 当root1和root2均为空,返回true
- 如果有一个root为空而另一个非空,返回false
- 比较root1和root2值,不相等则返回false
- 单层递归逻辑:
- 递归对root1.left和root2.right调用👉flag1
- 递归对root1.right和root2.left调用👉flag2
- 返回flag1且flag2
解法
class Solution {
public boolean isSymmetric(TreeNode root) {
return traverse(root.left, root.right);
}
public boolean traverse(TreeNode root1, TreeNode root2) {
if (root1 == null) {
if (root2 == null) {
return true;
}
else {
return false;
}
}
else {
if (root2 == null) {
return false;
}
else if (root1.val != root2.val) {
return false;
}
}
boolean flag1 = traverse(root1.left, root2.right);
boolean flag2 = traverse(root1.right, root2.left);
return flag1 & flag2;
}
}
LeetCode 104 二叉树的最大深度(递归法)
层序遍历中使用过层序遍历法,这次用递归法
思路
首先需要一个全局变量depth标识遍历时的深度,每次进入递归函数depth+1,要退出时就depth-1。 其次需要一个全局变量maxDepth记录遍历过程中最大的深度,最后在主函数中返回。初始化为0,方便对于空树输入直接返回0.
考虑递归函数三要素:
- 递归函数的参数和返回值 参数:根节点 返回值:空
- 递归函数的结束条件 根节点为空,立即返回
- 单层递归逻辑:
- depth+1后和maxDepth比较,更新maxDepth
- 分别对根节点的左子节点和右子节点递归调用
- depth-1
解法
class Solution {
int depth;
int maxDepth;
public int maxDepth(TreeNode root) {
depth = 0;
maxDepth = 0;
traverse(root);
return maxDepth;
}
public void traverse(TreeNode root) {
if (root == null) {
return ;
}
depth++;
maxDepth = Math.max(depth, maxDepth);
traverse(root.left);
traverse(root.right);
depth--;
}
}
LeetCode 111 二叉树的最小深度(递归法)
层序遍历中使用过层序遍历法,这次用递归法
思路
首先需要一个全局变量depth标识遍历时的深度,每次进入递归函数depth+1,要退出时就depth-1。
其次需要一个全局变量minDepth记录遍历过程中叶子节点的最小深度,最后在主函数中返回。
考虑递归函数三要素:
- 递归函数的参数和返回值 参数:根节点 返回值:空
- 递归函数的结束条件 根节点为空,立即返回
- 单层递归逻辑:
- depth+1
- 如果节点是叶子节点,把depth和minDepth比较,更新minDepth
- 分别对根节点的左子节点和右子节点递归调用
- depth-1
解法
class Solution {
int depth;
int minDepth;
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
depth = 0;
minDepth = Integer.MAX_VALUE;
traverse(root);
return minDepth;
}
public void traverse(TreeNode root) {
if (root == null) {
return ;
}
depth++;
if (root.left == null && root.right == null) {
minDepth = Math.min(depth, minDepth);
}
traverse(root.left);
traverse(root.right);
depth--;
}
}
今日收获总结
今日学习3小时,用递归法重做了一些题目。在写递归函数之前搞清楚递归三要素非常重要,可以减少bug的出现,也能捋清楚递归的过程