目录
题目一:二叉树的层序遍历
题目描述:
给你二叉树的根节点 root
,返回其节点值的 层序遍历 。(即逐层地,从左到右访问所有节点)。
思路分析:借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑
解法一:迭代法
class Solution {
public List<List<Integer>> res = new ArrayList<List<Integer>>(); // 二维数组保存最终结果
public List<List<Integer>> levelOrder(TreeNode root) {
checkFun(root);
return res;
}
public void checkFun(TreeNode node) {
if (node == null) return;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(node); // 结点不为空,则入队列
while (!queue.isEmpty()) { // 队列里没有元素时,终止循环
List<Integer> list = new ArrayList<>();
int len = queue.size(); // 每一层的元素个数
while (len > 0) {
TreeNode temp = queue.poll(); // 弹出出口元素
list.add(temp.val);
if (temp.left != null) queue.offer(temp.left);
if (temp.right != null) queue.offer(temp.right);
len--; // 每弹出一个元素,剩余弹出次数减一
}
res.add(list); // 每一层的元素以数组的形式存入二维数组
}
}
}
解法二:递归法
class Solution {
public List<List<Integer>> res = new ArrayList<List<Integer>>(); // 二维数组保存最终结果
public List<List<Integer>> levelOrder(TreeNode root) {
checkFun(root, 0);
return res;
}
// 在遍历左子树或者右子树的时候,涉及到向上或者向下遍历,为了让递归的过程中的同一层的节点放在同一个列表中,在递归时要记录深度 depth
public void checkFun(TreeNode node, Integer depth) {
if (node == null) return;
depth++; // 表示层数,
if (res.size() < depth) { // 如果depth >= res.size(),说明到下一层了,所以
// 要先把下一层的list初始化,防止下面add的时候出现空指针异常
List<Integer> list = new ArrayList<>();
res.add(list);
}
// depth表示的是第几层,这里访问到第几层,我们就把数据加入到第几层
res.get(depth - 1).add(node.val);
// 当前节点访问完之后,再使用递归的方式分别访问当前节点的左右子节点
checkFun(node.left, depth);
checkFun(node.right, depth);
}
}
题目二:翻转二叉树
题目描述:给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点
思路分析:以树的中间为分割线,把每个节点的左右孩子互换
解法一:递归法--前序遍历
class Solution {
// DFS:递归三部曲解决
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
swap(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
// 实现一个交换指针的swap()
public void swap(TreeNode root) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
解法二:迭代法
class Solution {
// BFS
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
ArrayDeque<TreeNode> 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);
}
size--;
}
}
return root;
}
// 实现一个交换指针的swap()
public void swap(TreeNode root) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
题目三:对称二叉树
题目描述:给你一个二叉树的根节点 root
, 检查它是否轴对称
思路分析:(具体步骤分析见代码随想录)
确定需要进行比较的节点,使用递归法中的后序遍历
解法一:递归法--后序遍历
class Solution {
public boolean isSymmetric(TreeNode root) {
return compare(root.left, root.right);
}
private boolean compare(TreeNode left, TreeNode right) { // 确定递归函数的参数和返回值
// 确定终止条件
if (left == null && right != null) {
return false;
}
if (left != null && right == null) {
return false;
}
if (left == null && right == null) {
return true;
}
if (left.val != right.val) {
return false;
}
// 处理单层递归逻辑,向下一层遍历
// 比较外侧
boolean compareOutside = compare(left.left, right.right);
// 比较内侧
boolean compareInside = compare(left.right, right.left);
return compareInside && compareOutside;
}
}
解法二:迭代法--普通队列
class Solution {
public boolean isSymmetric(TreeNode root) {
Queue<TreeNode> deque = new LinkedList<>();
deque.offer(root.left);
deque.offer(root.right);
while (!deque.isEmpty()) {
TreeNode leftNode = deque.poll();
TreeNode rightNode = deque.poll();
if (leftNode == null && rightNode == null) continue;
if (leftNode == null || rightNode ==null || leftNode.val != rightNode.val) {
return false;
}
deque.offer(leftNode.left);
deque.offer(rightNode.right);
deque.offer(leftNode.right);
deque.offer(rightNode.left);
}
return true;
}
}