今天将二叉树中层序遍历剩余的题目全部完成,并且还有一道翻转二叉树。
LeetCode117.填充每个节点的下一个右侧节点指针Ⅱ
这道题和昨天写的填充每个节点的下一个右侧节点指针唯一的区别是,昨天的题目中是满二叉树,但是今天的不是满二叉树,如此说来,昨天的那道题目应该会有更简单的解法,但是这道题也可以用我昨天的那个方法解出。
public static Node connect(Node root){
Queue<Node> queue=new LinkedList<>();
if (root==null){
return root;
}else {
queue.offer(root);
}
Node node;
while (!queue.isEmpty()){
int size=queue.size();
for (int i = 0; i < size; i++) {
node=queue.poll();
if (i==size-1){
node.next=null;
}else {
node.next=queue.peek();
}
if (node.left!=null){
queue.offer(node.left);
}
if (node.right!=null){
queue.offer(node.right);
}
}
}
return root;
}
每次遍历时,记录当前队列中的元素个数,也就是本次树行中的节点数目,当遍历到最后一个节点时,将其next指针置空,否则,该节点出队后,指向当前队列的队首元素,也就是右侧的下一个节点。整体的思路仍是层序遍历的思路。
LeetCode104.二叉树的最大深度
本题依旧可以使用层序遍历,定义一个计数器,记录遍历过的层数,直到层序遍历完成后,返回计数器的数值,即为二叉树一共有多少行,即二叉树的最大深度。
public static int maxDepth(TreeNode root){
if (root!=null) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
TreeNode node;
int count = 0;
while (!queue.isEmpty()){
int size=queue.size();
count++;
for (int i=0;i<size;i++) {
node=queue.poll();
if (node.left!=null){
queue.offer(node.left);
}
if (node.right!=null){
queue.offer(node.right);
}
}
}
return count;
} else {
return 0;
}
}
LeetCode111.二叉树的最小深度
这道题和上一道题正好相反,需要求出二叉树的最小深度。最大深度即为所有行数,只需完全遍历即可。而最小深度的逻辑相较略为复杂,如果一个节点既没有左子节点,也没有右子节点,那么它就是这条树枝的叶子节点。那么通过层序遍历,遍历到的第一个叶子节点所在的行数,就是二叉树的最小深度。
public static int minDepth(TreeNode root){
int count=0;
if (root==null){
return 0;
}else {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
TreeNode node;
while (!queue.isEmpty()){
int size=queue.size();
count++;
for (int i = 0; i < size; i++) {
node=queue.poll();
if (node.right==null&&node.left==null){
return count;
}
if (node.left!=null){
queue.offer(node.left);
}
if (node.right!=null){
queue.offer(node.right);
}
}
}
}
return count;
}
先判度是否是叶子节点,如果不是,进行其子节点的入队操作。
LeetCode226.翻转二叉树
这道题可以使用深度遍历,也可以使用广度遍历。使用深度遍历,可以使用前序遍历和后续遍历。
//前序遍历
public static TreeNode invertTree(TreeNode root){
if (root==null){
return root;
}else {
TreeNode temp=root.right;
root.right=root.left;
root.left=temp;
invertTree(root.left);
invertTree(root.right);
}
return root;
}
//后序遍历
public static TreeNode invertTree(TreeNode root){
if (root==null){
return root;
}else {
invertTree(root.left);
invertTree(root.right);
TreeNode temp=root.right;
root.right=root.left;
root.left=temp;
}
return root;
}
但是如果使用中序遍历的话,需要注意,当递归遍历完左子树后,进行左右子树的交换操作,这时如果再遍历右子树,其实是交换前的左子树,也就是左子树被遍历了两遍,所以是错误的。那么不能使用中序遍历解决这道题目吗?其实也不是,只需要解决我们刚刚发现提出的这个问题就可以了。在遍历完左子树后,交换左右子树,那么右子树就到了原来左子树的位置,所以继续遍历左子树即可。
//中序遍历
public static TreeNode invertTree(TreeNode root){
if (root==null){
return root;
}else {
invertTree(root.left);
TreeNode temp=root.right;
root.right=root.left;
root.left=temp;
invertTree(root.left);
}
return root;
}
这道题也可以使用层序遍历,我第一遍做这道题时,就使用层序遍历解决。层序遍历的操作一样,每次遍历到一个节点时,将其左右节点互换位置即可。
//层序遍历
public static TreeNode invertTree(TreeNode root){
if (root==null){
return root;
}else {
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
TreeNode node;
while(!queue.isEmpty()){
int size= queue.size();
for (int i = 0; i < size; i++) {
node=queue.poll();
if (node.left!=null){
queue.offer(node.left);
}
if (node.right!=null){
queue.offer(node.right);
}
TreeNode temp=node.right;
node.right=node.left;
node.left=temp;
}
}
return root;
}
}