文章目录
一、二叉树的锯齿形层序遍历
给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
解题思路
- 正常的层序遍历,使用队列来帮助我们记录每层的节点,只是本题要求我们偶数层的节点值要反着存。那那么在正常记录偶数层的节点值之后使用 把值反转一下就行了
代码实现及解析
java
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
Queue<TreeNode> queue=new LinkedList<>();
List<List<Integer>> ret=new ArrayList<>();
if(root==null) return ret;
queue.offer(root);
boolean flag=false;//代表奇数层
while(!queue.isEmpty()){
int size=queue.size();//记录本层的节点数
List<Integer> list=new ArrayList<>();
for(int i=0;i<size;i++){//for循环结束后只提取一层的节点
TreeNode node=queue.poll();
list.add(node.val);
//将该节点的孩子节点入队列
if(node.left!=null) queue.offer(node.left);
if(node.right!=null) queue.offer(node.right);
}
if(flag) Collections.reverse(list);//偶数层的节点值需要反转
ret.add(list);
flag=!flag;//变换奇偶层记录
}
return ret;
}
}
总结
复习解题思路
二、二叉树最大宽度
给你一棵二叉树的根节点 root ,返回树的 最大宽度 。
树的 最大宽度 是所有层中最大的 宽度 。
每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。
题目数据保证答案将会在 32 位 带符号整数范围内。

提示:
树中节点的数目范围是 [1, 3000]
-100 <= Node.val <= 100
解题思路
方法一(不可取):
- 我们可能会想到像正常层序遍历那样把空节点也入队列,只要处理好空节点的操作问题理论上可以达到要求,但是当根节点两边的子树都呈现单分支树的状态时(也就是每边都有1500个节点),最后一层的节点数可以达到恐怖的21500-1个,这个数目连double都存不下,所以该方法不可取。
方法二(采用节点编号):
- 我们仍然是使用层序遍历,将存在的节点入队列,但是我们要像堆结构那样对节点进行编号,并与对应节点一起储存,这样最后就可以使用两端节点的编号直接计算出该层的宽度。
- 有两种编号方式,一种是根节点编号为0,一种是根节点编号为1,这两种方式的孩子节点的计算公式是不一样的,但是忘了可以直接推导。
- 根节点编号为1:leftChild=parent*2 ,rightChild=parent*2+1;
- 根节点编号为0:leftChild=parent*2 +1,rightChild=parent*2+2;
- 我们使用ArrayList来模拟队列,更容易精准地定位到第一个和最后一个节点(两端节点来计算宽度),在代码中要着重熟悉一下如何使用ArrayList来模拟队列更新数据的方式(也就是将本层节点弹出并将它们的孩子节点入队列),我们使用的是每层创建一个新的ArrayList来储存下一层的节点,然后更新ArrayList。
小细节:方法一中列举的情况,即使为节点下标编号,下标也会溢出。但是当两下标相减后,即使溢出,结果也是正确的。
代码实现及解析
java
class Solution {
public int widthOfBinaryTree(TreeNode root) {
List<Pair<TreeNode,Integer>> queue=new ArrayList<>();//用ArrayList模拟队列
Pair<TreeNode,Integer> pair=new Pair<>(root,1);//将节点与它的编号绑定(也可以使用Map.Entry)
queue.add(pair);//将root入队列
int ret=0;//记录最大宽度
while(!queue.isEmpty()){
int k=queue.size();
//1.计算宽度
int wide=queue.get(k-1).getValue()-queue.get(0).getValue()+1;
ret=Math.max(ret,wide);
//2.放入下一层节点
List<Pair<TreeNode,Integer>> tmpQue=new ArrayList<>();//每层节点放入一个新的ArrayList中(ArrayList方法有限,这是最合适的一种模拟队列更新数据的方式)
for(Pair<TreeNode,Integer> x:queue){
TreeNode node=x.getKey();
if(node.left!=null){
Pair<TreeNode,Integer> tmp=new Pair<>(node.left,x.getValue()*2);
tmpQue.add(tmp);
}
if(node.right!=null){
Pair<TreeNode,Integer> tmp=new Pair<>(node.right,x.getValue()*2+1);
tmpQue.add(tmp);
}
}
queue=tmpQue;//更新队列
}
return ret;
}
}
注:Java标准库自身没有提供 Pair 通用公共类, 通常需要使用第三方库或特定JDK模块中的类。Leetcode可以直接使用,但是IDE中用不了,可以改使用Map.Entry
- 或者我们也可以直接自己现场实现一个自定义包装类(代码也不多,很实用):
java
class Wrapper {
TreeNode node;
int index;
public Wrapper() {
}
public Wrapper(TreeNode node, int index) {
this.node= node;
this.index = index;
}
public TreeNode getKey() {
return node;
}
public int getValue() {
return index;
}
}
总结
复习解题思路和代码实现及解析