剑指Offer 32 II 、III

88 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情

题目:就是将二叉树进行层序遍历,只不过变了输出的格式。其中II要求的输出是同一层的节点在一个list里面,III 要求按照层数的奇数偶数从左向右或者从右向左输出答案。

解题思路

思路很简单,首先说II,既然要求每一层的节点都在一层,那么我们直接记录每层节点数量即可,使用一个list保存当前层的结果,如果判定当前层节点已遍历完成则直接加入最终结果集,方法是使用一个变量记录每层节点,每当此变量变成0即本层已遍历完成,就将临时链表重置,并且维护这个变量,将此变量的值更新为队列的长度,不断循环更新此变量即可。而对于III的要求,我们可以用另一个变量来判断当前层属于第几层,奇数层则从右向左输出,偶数层则从左向右输出,那么在II的代码上只需加入最终结果的时候将list根据层数的判断是否需要进行反转,对于奇数将反转后的结果加入集合即可。根据上面的思路将代码进行合并可得最终III的代码为:

public List<List<Integer>> levelOrder3(TreeNode root) {
    if(root == null) return new ArrayList<>();
    ArrayList<List<Integer>> res = new ArrayList<>();
    ArrayDeque<TreeNode> queue = new ArrayDeque<>();
    queue.offer(root);
    int size = 1;
    int cur = 0;
    ArrayList<Integer> temp = new ArrayList<>();
    while(!queue.isEmpty()){
        TreeNode node = queue.poll();
        temp.add(node.val);
        size--;

        if(node.left!=null){
            queue.offer(node.left);
        }
        if(node.right!=null){
            queue.offer(node.right);
        }

        if(size==0){
            if(cur % 2==1){
                Collections.reverse(temp);
                res.add(temp);
            }else {
                res.add(temp);
            }
            cur++;
            size = queue.size();
            temp = new ArrayList<>();
        }
    }
    return res;
}

上述用到了Collections,实际上保存临时结果集我们可以采用LinkListed,因为LinkListed对于插入有两种方式,头插法和尾插法,这刚好对应了反转结果,当当前层为偶数的时候,我们可以采用尾插法,反之使用头插法即可,这样也能得到最终结果。