前言
我自己之前刷代码随想录刚好到这里,接下来就就是全新的旅程了。
二叉树层次遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
思路
这道题使用了队列这一数据结构,因为队列的特点是先进先出,所以可以当访问节点时从队列中弹出元素然后将他的子节点放入队列,因为子节点是后放进入的所以要访问完了当层的元素之后才可以访问,正好就是下一层的元素。
使用队列实现二叉树广度优先遍历,动画如下:
代码
//BFS--迭代方式--借助队列
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
if (root == null) {
return res;
}
queue.add(root);
while (!queue.isEmpty()) {
ArrayList<Integer> list = new ArrayList<>();
int currentLength = queue.size();
while (currentLength > 0) {
TreeNode poll = queue.poll();
list.add(poll.val);
if (poll.left != null) {
queue.add(poll.left);
}
if (poll.right != null) {
queue.add(poll.right);
}
currentLength--;
}
res.add(list);
}
return res;
}
注意
这道题的返回值是List<List<Integer>>,要把当层的元素放到一个列表中,那么怎么在遍历的时候确定盖层元素有多少个呢,需要定义一个变量currentLength保存当前长度,每访问一个当前节点就currentLength--,当currentLength==0时正好访问完当前层,而队列中的元素正好就是下一层的所有节点,所以再次赋值currentLength。
226.翻转二叉树 (递归)
翻转一棵二叉树。
思路
遍历的过程中去翻转每一个节点的左右孩子就可以达到整体翻转的效果。 注意只要把每一个节点的左右孩子翻转一下,就可以达到整体翻转的效果
我们下文以前序遍历为例,通过动画来看一下翻转的过程:
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return root;
}
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);
invertTree(root.right);
return root;
}
注意
这道题不能使用中续遍历,因为中序遍历处理根节点时左右节点会交换,左后孩子会交换,最后遍历右孩子的时候其实又便利了一次左孩子。
101. 对称二叉树 (递归)
给定一个二叉树,检查它是否是镜像对称的。
思路
首先想清楚,判断对称二叉树要比较的是哪两个节点,要比较的可不是左右节点!
对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了其实我们要比较的是两个树(这两个树是根节点的左右子树) ,所以在递归遍历的过程中,也是要同时遍历两棵树。
那么如果比较呢?
比较的是两个子树的里侧和外侧的元素是否相等。如图所示:
代码
public boolean isSymmetric1(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 compareOutside && compareInside;
}
注意
if (left == null && right == null)的判断必须在if (left.val != right.val)前,不然可能会造成空指针异常。
结束
作业好多啊,这周还有考试。