力扣第103题-二叉树的锯齿形层序遍历

316 阅读3分钟

「这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

前言

力扣第103题 二叉树的锯齿形层序遍历 如下所示:

给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

例如:给定二叉树 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回锯齿形层序遍历如下:

[
  [3],
  [20,9],
  [15,7]
]

一、思路

题目意思很简单,需要返回锯齿遍历的结果

锯齿遍历是指从 第一层从右至左,第二层从左至右(根节点可忽略)。为了更好的理解这一行为,具体的路径如下图所示:

image.png

上图中 锯齿遍历 的结果为:[[1], [3,2],[4,5,6,7]]

这一题刚开始做的时候还是有点绕的,不过只要画个图模拟一下遍历的顺序就会清晰很多了。我们还是用上图中的树作为例子,用来分析。

在观察了第二层的节点遍历顺序和第三层节点的遍历顺序后,不难发现:当前层最先遍历到的节点的子节点,是下一层最后遍历的节点

例如第二层中的节点 3 是第二层最先遍历的。但是它的左右孩子子节点 67 是第三层最后面遍历的。

还有一点就是:在同一层中,如果当前层数是偶数,则右节点优先遍历。如果当前层数为奇数,则左节点优先遍历 (例如第三层中的 6 是要先于 7 遍历的)

综上所述,基于这种先进后出的结构,我们可以使用 来保存遍历的节点,正好可以对应上当前层中先遍历,下一层中后遍历。

举个例子

我们以 [3,9,20,null,null,15,7] 来举例,重点讲述一下 中存储元素

Deque<TreeNode> currentLevel:当前层节点
Deque<TreeNode> nextLevel:下一层节点

  1. 遍历 第一层 节点 [3],先将它的左孩子 9 入栈,再将右孩子 20 入栈。nextLevel 栈中为 9 -> 20
  2. 遍历第二层,currentLevel 栈顶一直出栈。第一个节点为 20,将它的右孩子 7nextLevel 栈,再将它的右孩子 15nextLevel 栈。第二个节点为 9,没有左右孩子故不入栈。nextLevel 栈中为 7 -> 15
  3. 遍历第三层,currentLevel出栈。第一个节点为 15,第二个节点为 7,都没有左右孩子,故不入栈。
  4. 最终返回遍历的各节点值 [[3], [20, 9], [15, 7]] 即可

二、实现

实现代码

注意:因为考虑到不特殊处理根节点,所以我们认为根节点为第 0 层。所以奇偶性判断与思路中不是一致的

    List<List<Integer>> ret = new ArrayList<>();

    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        if (root!=null) {
            Deque<TreeNode> stack = new LinkedList<>();
            stack.push(root);
            dfs(stack);
        }
        return ret;
    }

    public void dfs(Deque<TreeNode> currentLevel) {
        if (currentLevel.size() < 1)
            return;
        List<Integer> temp = new ArrayList<>();
        Deque<TreeNode> nextLevel = new LinkedList<>();
        // 遍历当前层级
        while (!currentLevel.isEmpty()){
            TreeNode treeNode = currentLevel.pop();
            temp.add(treeNode.val);
            // 因为需要添加下一层,所以是 size + 1
            if((ret.size() + 1) % 2 == 1) { // 奇数层:先加左边,再加右边
                if (treeNode.left != null){
                    nextLevel.push(treeNode.left);
                }
                if (treeNode.right != null){
                    nextLevel.push(treeNode.right);
                }
            } else {    // 偶数层:先加右边,再加左边
                if (treeNode.right != null){
                    nextLevel.push(treeNode.right);
                }
                if (treeNode.left != null){
                    nextLevel.push(treeNode.left);
                }
            }
        }
        ret.add(temp);
        dfs(nextLevel);
    }

测试代码

public static void main(String[] args) {
    TreeNode treeNode = new TreeNode(1,
            new TreeNode(2,new TreeNode(4), null),
            new TreeNode(3, null, new TreeNode(5)));
    new Number103().zigzagLevelOrder(treeNode);
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~