Algorithm Notes
  • Introduction
  • Search & Backtracking 搜索与回溯
    • Tree 与 BackTracking 的比较
    • Subsets, Combination 与 Permutation
    • Subsets & Combinations & Combination Sum
    • 枚举法
    • N 皇后 + 矩阵 Index Trick
    • Sudoku 数独 + 矩阵 Index Trick
    • Word Ladder I & II
    • Number of ways 类
    • DFS flood filling
    • Strobogrammatic 数生成
    • String 构造式 DFS + Backtracking
    • Word Pattern I & II
    • (G) Binary Watch
    • (FB) Phone Letter Combination
    • 常见搜索问题的迭代解法
  • String,字符串类
    • 多步翻转法
    • Substring 结构和遍历
    • Palindrome 问题
    • Palindrome Continued
    • String / LinkedList 大数运算
    • 序列化与压缩
    • 5/24 String 杂题
    • Knuth–Morris–Pratt 字符串匹配
    • Lempel–Ziv–Welch 字符串压缩算法
    • (G) Decode String
    • (G) UTF-8 Validation
  • Binary Tree,二叉树
    • 各种 Binary Tree 定义
    • LCA 类问题
    • 三序遍历,vertical order
    • Post order traversal 的应用
    • Min/Max/Balanced Depth
    • BST
    • 子树结构
    • Level Order traversal
    • Morris 遍历
    • 修改结构
    • 创建 / 序列化
    • 子树组合,BST query
    • 路径与路径和
    • NestedInteger 类
    • (FB) 从 Binary Tree Path 看如何递归转迭代
    • (FB) Binary Tree Path 比较路径大小
    • 比较好玩的 Binary Tree 概率题
  • Segment & Fenwick Tree,区间树
    • Segment Tree 基础操作
    • Segment Tree 的应用
    • Fenwick Tree (Binary Indexed Tree)
    • Range Sum Query 2D - Immutable
  • Union-Find,并查集
    • Union-Find,并查集基础
    • Union-Find, 并查集应用
  • Dynamic Programming, 动态规划
    • 6/20, 入门 House Robber
    • 7/12, Paint Fence / House
    • 6/24, 滚动数组
    • 6/24, 记忆化搜索
    • 6/24, 博弈类 DP
    • 博弈类DP, Flip Game
    • 6/25, 区间类DP
    • 6/27, subarray 划分类,股票
    • 7/2, 字符串类
    • Bomb Enemies
    • 8/2,背包问题
    • (G) Max Vacation
    • (11/4新增) AST 子树结构 DP
  • LinkedList,链表
    • 6/9, LinkedList,反转与删除
    • 6/11, LinkedList 杂题
    • (FB) 链表的递归与倒序打印
  • LinkedIn 面经,算法题
    • 6/17, LinkedIn 面经题
    • 6/28, LinkedIn 面经题
    • 7/6, LinkedIn 面经
    • Shortest Word Distance 类
    • DFA Parse Integer
  • Two Pointers,双指针
    • 3 Sum, 3 Sum Closest / Smaller, 4 Sum
    • 对撞型,灌水类
    • 对撞型,partition类
    • Wiggle Sort I & II
    • 双指针,窗口类
    • 双指针,窗口类
    • Heap,排序 matrix 中的 two pointers
  • Bit & Math,位运算与数学
    • Bit Manipulation,对于 '1' 位的操作
    • Math & Bit Manipulation, Power of X
    • 坐标系 & 数值计算类
    • Add Digits
    • 用 int 做字符串 signature
  • Interval 与 扫描线
    • Range Addition & LCS
    • 7/5, Interval 类,扫描线
  • Trie,字典树
    • 6/9, Trie, 字典树
  • 单调栈,LIS
    • 4/13 LIS
    • 栈, 单调栈
    • Largest Divisible Subset
  • Binary Search 类
    • Matrix Binary Search
    • Array Binary Search
    • Find Peak Element I & II
    • **Median of Two Sorted Arrays
  • Graph & Topological Sort,图 & 拓扑排序
    • 有向 / 无向 图的基本性质和操作
    • 拓扑排序, DFS 做法
    • 拓扑排序, BFS 做法
    • Course Schedule I & II
    • Alien Dictionary
    • Undirected Graph, BFS
    • Undirected Graph, DFS
    • 矩阵,BFS 最短距离探索
    • 欧拉回路,Hierholzer算法
    • AI, 迷宫生成
    • AI, 迷宫寻路算法
    • (G) Deep Copy 无向图成有向图
  • 括号与数学表达式的计算
  • Iterator 类
  • Majority Element,Moore's Voting
  • Matrix Inplace Operations
  • 常见数据结构设计
  • (G) Design / OOD 类算法题
  • 随机算法 & 数据结构
  • (FB) I/O Buffer
  • (FB) Simplify Path, H-Index I & II
  • (FB) Excel Sheet, Remove Duplicates
  • Integer 的构造,操作,序列化
  • Frequency 类问题
  • Missing Number 类,元素交换,数组环形跳转
  • 8/10, Google Tag
  • (FB) Rearrange String k Distance Apart
  • Abstract Algebra
    • Chap1 -- Why Abstract Algebra ?
    • Chap2 -- Operations
    • Chap3 -- The Definition of Groups
Powered by GitBook
On this page
  • Binary Tree Level Order Traversal
  • Binary Tree Level Order Traversal II
  • Binary Tree Zigzag Level Order Traversal
  • Populating Next Right Pointers in Each Node
  • Populating Next Right Pointers in Each Node II
  • Binary Tree Right Side View

Was this helpful?

  1. Binary Tree,二叉树

Level Order traversal

Previous子树结构NextMorris 遍历

Last updated 4 years ago

Was this helpful?

送分题,就当热手了。

迭代的写法和 CLRS 的伪代码一模一样。

public class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        if(root != null) queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            List<Integer> list = new ArrayList<>();
            for(int i = 0; i < size; i++){
                TreeNode node = queue.poll();
                list.add(node.val);
                if(node.left != null) queue.offer(node.left);
                if(node.right != null) queue.offer(node.right);
            }
            rst.add(list);
        }

        return rst;
    }
}

这题的递归写法挺有意思的。

  • 递归写法本质上是对 binary tree 做了一个 pre-order dfs.

  • 更靠近 root 的层一定会比下一层先建出来

  • 对于同一个 level,左面的节点一定比右面节点先 add.

public class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        dfs(rst, root, 0);
        return rst;
    }

    private void dfs(List<List<Integer>> rst, TreeNode root, int level){
        if(root == null) return;

        if(level >= rst.size()){
            rst.add(new ArrayList<Integer>());
        }

        rst.get(level).add(root.val);

        dfs(rst, root.left, level + 1);
        dfs(rst, root.right, level + 1);
    }
}

写法一样,最后 reverse 一下就好了。

public class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
       List<List<Integer>> rst = new ArrayList<List<Integer>>();
        dfs(rst, root, 0);
        Collections.reverse(rst);
        return rst;
    }

    private void dfs(List<List<Integer>> rst, TreeNode root, int level){
        if(root == null) return;

        if(level >= rst.size()){
            rst.add(new ArrayList<Integer>());
        }

        rst.get(level).add(root.val);

        dfs(rst, root.left, level + 1);
        dfs(rst, root.right, level + 1);
    }
}

挺 trivial 的问题。

public class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        boolean reverse = false;
        if(root != null) queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            List<Integer> list = new ArrayList<Integer>();
            for(int i = 0; i < size; i++){
                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(reverse) Collections.reverse(list);

            rst.add(list);
            reverse = !reverse;
        }

        return rst;
    }
}

Level order 的写法非常的 trivial,不过这题规定不许手动建任何额外空间(不许存level或者用迭代写,虽然递归也用空间)

考虑到这题给定 perfect tree,不需要考虑中间有拐弯或者空位的问题,递归解决的思路就是用一个 helper 函数传入当前的两个节点(为上一个节点的 left/right child)

  • 连接左右

  • 迭代依次连接左节点右侧的 path 与 右节点左侧的 path

  • 递归下一层

public class Solution {

    public void connect(TreeLinkNode root) {
        if(root == null) return;
        if(root.left == null && root.right == null) return;

        helper(root.left, root.right);
    }

    private void helper(TreeLinkNode p, TreeLinkNode q){
        if(p == null && q == null) return;
        if(p == null || q == null) return;

        p.next = q;

        TreeLinkNode l = p;
        TreeLinkNode r = q;
        while(q.right != null && q.left != null){
            p = p.right;
            q = q.left;

            p.next = q;
        }

        helper(l.left, l.right);
        helper(r.left, r.right);
    }
}

真正的 O(1) 空间是用固定数量的指针进行迭代循环。

  • 这种写法是真正的 level order 添加,利用了上一层完成之后的 next 指针手动做了 level order 遍历。

public class Solution {
    public void connect(TreeLinkNode root) {
        if(root == null) return;

        TreeLinkNode cur = root;
        TreeLinkNode leftMost = null;
        while(cur.left != null){
            leftMost = cur.left;
            while(cur != null){
                cur.left.next = cur.right;
                if(cur.next == null){
                    cur.right.next = null;
                } else {
                    cur.right.next = cur.next.left;
                }
                cur = cur.next;
            }
            cur = leftMost;
        }
    }
}
  • 在参考了下一题 follow up 的写法之后,这类问题的通解:

public class Solution {
    public void connect(TreeLinkNode root) {
        while(root != null){
            TreeLinkNode dummy = new TreeLinkNode(0);
            TreeLinkNode cur = dummy;
            for( ; root != null; root = root.next){
                if(root.left != null){
                    cur.next = root.left;
                    cur = cur.next;
                }
                if(root.right != null){
                    cur.next = root.right;
                    cur = cur.next;
                }
            }
            root = dummy.next;
        }
    }
}

搞了半天一直处于一个追着各种 test case 改 Bug 的阶段,而且要改的细节越来越多。。。写题如果发现自己陷入了这个阶段,还是果断换思路把。

这题的迭代思路和上一题一样,充分利用好上一层已经是连好的next指针来做 level order. 然而有几个很烦的地方需要处理:

  • 中间有空缺节点的话,怎么让上层找到“下一个”正确的节点

  • 如果某一层最左边有空缺的话,如何在进入下一层的时候找到正确的起点

这个解法的思路非常简洁优美。因为对题本质的理解更进一步了:

  • 我们要做的其实是 level order 建一个 LinkedList 出来。

于是这题几个最烦人的细节处理,都可以靠 dummy node 解决。

  • 这题也是继 word ladder 之后另一个不同的 for 循环写法,字符和链表都很适合用 for loop 实现遍历。

public class Solution {
    public void connect(TreeLinkNode root) {
        while(root != null){
            TreeLinkNode dummy = new TreeLinkNode(0);
            TreeLinkNode cur = dummy;
            for( ; root != null; root = root.next){
                if(root.left != null){
                    cur.next = root.left;
                    cur = cur.next;
                }
                if(root.right != null){
                    cur.next = root.right;
                    cur = cur.next;
                }
            }
            root = dummy.next;
        }
    }
}

这题本质上还是在做 level order 遍历,因为最终结果上 node 是按层数依次添加的。

于是回想下递归版的 level order traversal,我们做 dfs pre-order

  • 【中,左,右】 的顺序可以保证上面一层的节点永远会比下一层的先建立;

  • 同时对于每一层,我们一定会先发现最左面的节点,而后才是右面依次发现。

把这个性质根据题意改一下,我们就有了

  • 【中,右,左】 首先保证了 level order,因为对于所有子树,中节点要比左右子树先执行;

  • 同时因为子树顺序是 【右,左】,同一 level 的节点一定是从右到左被发现的。

因此只要注意判断条件,只把第一次发现的元素添加进去,然后做改变顺序版 preorder traversal 就好了。

  • 同理也很容易解 Left Side View.

public class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> list = new ArrayList<Integer>();

        helper(root, list, 0);

        return list;
    }

    private void helper(TreeNode root, List<Integer> list, int level){
        if(root == null) return;

        if(level == list.size()) list.add(root.val);
        helper(root.right, list, level + 1);
        helper(root.left, list, level + 1);
    }
}

Binary Tree Level Order Traversal
Binary Tree Level Order Traversal II
Binary Tree Zigzag Level Order Traversal
Populating Next Right Pointers in Each Node
Populating Next Right Pointers in Each Node II
Binary Tree Right Side View