leetcode的第103题,二叉树的锯齿形层次遍历,java实现

15 篇文章 0 订阅

题目链接

一、层次遍历思想,迭代法

根据题目名,最先想到的是采用层次遍历的方法,但是一分析发现,默认的队列记录法不好用了。

经过画图分析,在开队列迭代层序遍历思想的基础上,开两个堆栈,分别记录奇数层和偶数层的节点。
在这里插入图片描述
奇数层从右往左压栈,出栈时的循序,是从左往右的,把其子节点压到偶数层堆栈,偶数层堆栈出栈的顺序就符合图示要求,即从右往左的。如此递归循环。

  • 怎么记录现在在哪一层?

每一轮,完成一层的遍历后,levels++,levels指示所在层数。每一轮,堆栈中只包含该层的节点,通过读取堆栈size(),控制for循环次数为size次实现。

运行结果

执行结果:通过
执行用时:2 ms

代码与注释

class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        // 先入后出:用堆栈
        Stack<TreeNode> stack1 = new Stack<>(); // 奇数层堆栈
        Stack<TreeNode> stack2 = new Stack<>(); // 偶数层堆栈
        List<List<Integer>> ans = new LinkedList<List<Integer>>();
        if (root == null) return ans;

        
        int levels = 0;
        stack1.push(root);
        while (!stack1.isEmpty() || !stack2.isEmpty())
        {
            levels ++;
            LinkedList<Integer> tmp = new LinkedList<>();
            // 奇数层:从左到右
            if (levels % 2 == 1)
            {
                int len = stack1.size();
                
                for (int i = 0; i < len; i++)
                {
                    root = stack1.pop();
                    tmp.add(root.val);
                    if (root.left != null) stack2.push(root.left);
                    if (root.right != null) stack2.push(root.right);
                }
            }
            // 偶数层:从右往左
            else
            {
                int len = stack2.size();
                
                for (int i = 0; i < len; i++)
                {
                    root = stack2.pop();
                    tmp.add(root.val);
                    if (root.right != null) stack1.push(root.right);
                    if (root.left != null) stack1.push(root.left);
                }
            }
            ans.add(tmp);
        }
        return ans;

    }
}

二、DFS思想,递归法

传统的递归法也可以实现要求的层次遍历。

小技巧:
1.利用add()函数特性,在特定位置持续写入元素,相当于将一串数据反序,即add(0, root.val)操作。简单又好用。
2.判断奇数偶数不仅可以用levels % 2 == 0,还可以用位运算levels & 1 == 0。

  • 何时添加ans新层?
    条件:levels == ans.size(),获取ans创建的行数,如果跟现在的层数相同,则建立新行。

运行结果

执行结果:通过
执行用时:1 ms, 在所有 Java 提交中击败了98.78%的用户
内存消耗:36 MB, 在所有 Java 提交中击败了72.60%的用户

代码与注释

class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> ans = new ArrayList<>();
        dfs(root, 0, ans);
        return ans;
    }
    private void dfs(TreeNode root, int levels, List<List<Integer>> ans)
    {
        if (root == null) return;

        if (levels == ans.size()) ans.add(new ArrayList<Integer>());

        // 奇数行
        if (levels % 2 == 0) ans.get(levels).add(root.val);
        // 偶数行,利用add(),新数会把老数往后挤,效果就是反序
        else ans.get(levels).add(0, root.val);

        dfs(root.left, levels + 1, ans);
        dfs(root.right, levels + 1, ans);

    }
}

总结

  1. 采用二叉树常见递归方法,在此基础上添加约束条件。
  2. 给出添加结果List新行条件为:与当前层数相同,防止递归添加过多行。
  3. 进入下次递归前,添加val到结果列表。
  4. 区分奇偶行,将val添加到该层对应列表的头或尾。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值