day_15
-
102 - 二叉树的层序遍历 - 题目链接/文章讲解/视频讲解
-
226 - 翻转二叉树 - 题目链接/文章讲解/视频讲解
-
101 - 对称二叉树 - 题目链接/文章讲解/视频讲解
题目连接
102 - 二叉树的层序遍历
两种方法:
- 递归(深度遍历,取出值,给每一个节点赋上以一个深度标记)
- 将同一深度的节点值存储在一起,就得到了目标的层的层序遍历结果
public class LevelOrderTraversalRecursion {
// 存储层序节点的 list
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
levelOrderRecursion(root, 0);
return res;
}
public void levelOrderRecursion(TreeNode node, int deep){
if (node == null) return;
deep++; // 给节点的深度赋值
// res.size < deep 说明当前的深度还没有遍历到,给res 里新增一个存储当前深度的 list
// 递归是使用深度遍历来获取层序单层节点,选用前序遍历的方式,获取到跟节点后就添加到目标数组里
if (res.size() < deep) {
List<Integer> item = new ArrayList<Integer>();
res.add(item);
}
res.get(deep - 1).add(node.val); // 中
levelOrderRecursion(node.left, deep); // 左
levelOrderRecursion(node.right, deep); // 右
}
}
- 迭代
- 直接使用队列维护一整层的节点,继进行处理即可
public class LevelOrderTraversalQueue {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>(); // 中序遍历的结果列表
Queue<TreeNode> queue = new LinkedList<>(); // 对接口的实现如何查看?
if (root == null) return res;
queue.add(root);
while (!queue.isEmpty()){
int size = queue.size(); // 上一层有几个
List<Integer> upLevel = new ArrayList<>();
while (size > 0){
TreeNode cur = queue.poll();
upLevel.add(cur.val);
if (cur.left != null) queue.add(cur.left);
if (cur.right != null) queue.add(cur.right);
size--;
}
res.add(upLevel);
}
return res;
}
}
226 - 翻转二叉树
想要翻转它,其实就把每一个节点的左右孩子交换一下就可以了
问题是:前中后序应该选哪一种遍历顺序?
使用前序遍历处理子树,这是因为,
反转是先将左右子树进行反转操作,再将子树的左右反转
这种先操作根节点,再操作左右节点的顺序,正是前序遍历过程
typedef struct TreeNode TreeNode;
// 对二叉树操作的时候,一定要选择好遍历的顺序
struct TreeNode* invertTree(struct TreeNode* root){
if (root == NULL){
return NULL;
}
// 使用前序遍历处理子树,这是因为,
// 反转是先将左右子树进行反转操作,再将子树的左右反转
// 这种先操作根节点,再操作左右节点的顺序,正是前序遍历过程
invert(root);
return root;
}
// 在这里进行递归处理
void invert(TreeNode* root) {
if (root == NULL) return;
TreeNode* temp = root -> left;
root -> left = root -> right;
root -> right = temp;
invert(root->left);
invert(root->right);
}
101 - 对称二叉树
- 思路
- 从跟节点逐渐向下判断,每一级的节点是否相同
- 里面的情况中,不写 eles 是因为不为空且相同的时候,会自动走到这里
- 如果一开始遇到 false 的情况,直接 return,不用向下继续遍历
- 假设 outside 中间有跟节点不同,遍历到该节点的时候,就会直接 return false,不会继续向下了,会将该节点的判断结果一路返回
- 再得出 inside 的匹配结果
- 如果左右都对称就返回true ,有一侧不对称就返回false
typedef struct TreeNode TreeNode;
bool isSymmetric(struct TreeNode* root){
if (root == NULL) return true;
return judgeNodeSame(root->left, root->right);
}
// 后续遍历,需要先一路递归到叶子节点才行
bool judgeNodeSame(TreeNode* left, TreeNode* right){
if (left == NULL && right != NULL) return false; // 先看根节点是否相同,相同就继续向下,不同就返回
else if (left != NULL && right == NULL) return false; //
else if (left == NULL && right == NULL) return true; //
else if (left -> val != right -> val) return false; // 左右不为空,且不相等,只剩左右相等的情况了
// 左右相等,向下遍历
bool outside = judgeNodeSame(left -> left, right -> right); // 左
bool inside = judgeNodeSame(left -> right, right -> left); // 右
bool isSame = outside && inside; // 左子树:中、 右子树:中 (逻辑处理)
return isSame;
}