题目描述(传送门)
给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
示例
例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回锯齿形层序遍历如下:
[
[3],
[20,9],
[15,7]
]
思路
使用两个栈结构,分别是左优先栈和右优先栈;
左优先栈:注意是入栈时先加入右子树在加入左子树,因为这样你的出栈顺序才是从左往右的。
右优先栈刚好相反:入栈时先加入左子树在加入右子树,因为这样你的出栈顺序才是从右往左的。
然后将root加入左优先栈,也就是第一层(从左往右遍历)。
进入循环,左优先栈出栈,右优先栈进栈。当左优先栈(当前层)出栈完毕这时右优先栈也就将下一层元素入栈完毕。
左优先栈空了说明一层结束,接下来右优先栈出栈,同时给左优先栈加入下一层元素。
这样循环通过左右优先栈实现锯齿形便利,当两个栈都为空时,则遍历结束。
可能有些绕,那就看代码注释:
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> list = new ArrayList<>();
if (root == null) {
return list;
}
Deque<TreeNode> leftstack = new LinkedList<>();// 左优先栈(先加入右子树再加入右子树)
Deque<TreeNode> rightstack = new LinkedList<>();// 右优先栈 与上边相反
leftstack.push(root);//先从左往右,所以root加入左优先栈
while (!leftstack.isEmpty() || !rightstack.isEmpty()) {
//只要有一个不为空说明就没有便利结束
// 因为第一层root已经加入左优先栈,下来就给右优先栈加入左右子树。
// 如果不为空说明还是上一层的,只有空了才能加入
if (rightstack.isEmpty()) {
List<Integer> tempList = new ArrayList<>();
while (!leftstack.isEmpty()) {
// 左优先(本层)不为空,向右优先(下一层)加入左右子树
TreeNode temp = leftstack.peek();
tempList.add(temp.val);
//在这里,左优先栈是出栈状态,右优先栈是进栈状态。这和下边的进栈顺序不同也就实现锯齿形层序遍历
if (temp.left != null) {
rightstack.push(temp.left);
}
if (temp.right != null) {
rightstack.push(temp.right);
}
leftstack.pop();// 左优先出栈,左优先栈循环出栈,出栈时加入每个的左右子树
}
list.add(tempList);// 走到这里说明左优先栈为空了,说明本层也就便利完毕,同时下一层元素也就加入了右优先栈。将本层元素加入list
} else {
// 与上边刚好相反
List<Integer> tempList = new ArrayList<>();
while (!rightstack.isEmpty()) {
TreeNode temp = rightstack.peek();
tempList.add(temp.val);
if (temp.right != null) {
leftstack.push(temp.right);
}
if (temp.left != null) {
leftstack.push(temp.left);
}
rightstack.pop();
}
list.add(tempList);
}
}
//走到这里,循环结束说明两个栈内都为空了,说明二叉树遍历完毕
return list;
}
}