这题需要将每一层的数返回,一层是一个数组,所以需要嵌套使用。且二叉树本身不能存储数据,所以我们要借助栈来实现。代码如下:
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> que=new LinkedList<>();
List<List<Integer>> result=new ArrayList<>();
if(root!=null){
que.offer(root);
}
while(!que.isEmpty()){
List<Integer> list=new ArrayList<>();
int size=que.size();
while(size!=0){
TreeNode node=que.poll();
list.add(node.val);
if(node.left!=null){
que.offer(node.left);
}
if(node.right!=null){
que.offer(node.right);
}
size--;
}
result.add(list);
}
return result;
}
}
函数首先创建一个队列 Queue<TreeNode> 用来进行广度优先搜索,同时创建一个 List<List<Integer>> result 用来存储最终结果。如果根节点 root 不为空,就先把根节点加入队列。接下来进入循环,只要队列不为空就继续遍历。每一次循环代表处理树的一层,先通过 int size = que.size() 记录当前队列中的节点数量,这个数量就是当前层的节点个数。然后创建一个新的 List<Integer> list 用来存储这一层的所有节点值。接着通过 while(size != 0) 循环依次取出这一层的节点,每次用 que.poll() 从队列中取出队头节点,并把该节点的值 node.val 加入 list 中。如果这个节点存在左孩子,就把左孩子加入队列;如果存在右孩子,就把右孩子也加入队列,这样下一层的节点就被依次放入队列中。每处理完一个节点就让 size--,直到当前层所有节点都处理完。当前层遍历结束后,把这一层的 list 加入到结果列表 result 中。然后继续处理队列中的下一层节点。最终当队列为空时说明整棵树已经遍历完成,函数返回 result,其中每个子列表都表示二叉树的一层节点。
226. 翻转二叉树
这道题这段代码实现的是二叉树的镜像翻转,也就是把二叉树中每个节点的左子树和右子树进行交换。我们有三种方法,前序遍历、后序遍历、中序遍历。代码如下:
前序遍历:
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null){
return root;
}
swap(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
public void swap(TreeNode root){
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
使用的是递归思想。首先判断当前节点 root 是否为空,如果为空说明已经遍历到叶子节点的下方,没有需要处理的节点,直接返回 root。如果节点不为空,就调用 swap(root) 方法,将当前节点的左孩子和右孩子进行交换。swap 方法通过一个临时变量 temp 保存原来的左孩子,然后把右孩子赋值给 root.left,再把原来的左孩子赋值给 root.right,从而完成左右子树的交换。交换完当前节点的左右子树后,再分别对新的左子树 invertTree(root.left) 和新的右子树 invertTree(root.right) 继续递归执行同样的操作,这样整棵树的每个节点都会完成左右子树的交换。最后返回根节点 root,此时整棵二叉树已经被翻转成它的镜像结构。
后序遍历:
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null){
return root;
}
invertTree(root.left);
invertTree(root.right);
swap(root);
return root;
}
public void swap(TreeNode root){
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
只是把swap函数移到了后面。
那么中序遍历只需把swap移到中间就行了吗?答案是:不是的。
中序遍历是中左右,首先在左子树中会把1,3交换,变成3,1,之后交换2,7,变成7,2,此时是
此时交换右边是3,1,相当于交换了两次。所以我们要把invertTree(root.right);写为invertTree(root.left);代码如下:
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null){
return root;
}
invertTree(root.left);
swap(root);
invertTree(root.left);
return root;
}
public void swap(TreeNode root){
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
101. 对称二叉树
这题比较简单,我们要比较左右子树是否相同,我们把左子树的左边和右子树的右边称为外侧,左子树的右边和右子树的左边成为内侧,我们要比较的是外侧是否相同,内侧是否相同。我们可以分为以下几类:1.左右子树都为空,则返回true。2.左右子树都不为空,但值不相同,返回false。3.左为空右不为空,返回false。4.左不为空,右为空,返回false。代码如下:
class Solution {
public boolean isSymmetric(TreeNode root) {
return compare(root.left,root.right);
}
public boolean compare(TreeNode left,TreeNode right){
if(left==null&&right==null){
return true;
}else if(left==null&&right!=null){
return false;
}else if(left!=null&&right==null){
return false;
}else if(left.val!=right.val){
return false;
}
boolean outside=compare(left.left,right.right);
boolean inside=compare(left.right,right.left);
return outside&&inside;
}
}
我们分别比较外侧内侧,并将结果返回。
104. 二叉树的最大深度
首先要理解高度和深度,那很接单==简单,高度就是从下往上数,深度是从下往上数,但其实你看最大的高度和深度是一样的,所以我们这题可以用求高度的办法来写,代码如下:
class Solution {
public int maxDepth(TreeNode root) {
return getHeight(root);
}
public int getHeight(TreeNode root){
if(root==null){
return 0;
}
int leftHeight=getHeight(root.left);
int rightHeight=getHeight(root.right);
return Math.max(leftHeight,rightHeight)+1;
}
}
这题使用后序遍历来写,每次返回的高度加一,表示比下面高一层。