• LeetCode算法题-N-ary Tree Postorder Traversal(Java实现)


    这是悦乐书的第269次更新,第283篇原创

    01 看题和准备

    今天介绍的是LeetCode算法题中Easy级别的第136题(顺位题号是590)。给定一个n-ary树,返回其节点值的后序遍历。例如,给定一个3-ary树:

         1
      /  |  
     3   2   4
    / 
    5  6
    

    其后序遍历结果为:[5,6,3,2,4,1]。

    注意:递归解决方案是微不足道的,你可以用迭代的方式做吗?

    本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

    02 第一种解法

    和昨天的题目求n-ary树的前序遍历结果类似,今天的题目是求其后序遍历结果,也就是先左子树,再右子树,最后根节点,依旧使用递归的方法,只不过是将辅助方法里的一行代码移动到for循环后面去执行而已,其他的地方和昨天的代码没什么区别。

    /*
    // Definition for a Node.
    class Node {
        public int val;
        public List<Node> children;
    
        public Node() {}
    
        public Node(int _val,List<Node> _children) {
            val = _val;
            children = _children;
        }
    };
    */
    class Solution {
        public List<Integer> postorder(Node root) {
            if (root == null) {
                return new ArrayList<Integer>();
            }
            List<Integer> list = new ArrayList<Integer>();
            getValue(root, list);
            return list;
        }
    
        public List<Integer> getValue(Node root, List<Integer> list) {
            if (root == null) {
                return null;    
            } 
            if (root.children != null) {
                for (Node n : root.children) {
                    getValue(n, list);
                }    
            }
            list.add(root.val);
            return list;
        }
    }
    

    03 第二种解法

    使用迭代的方式。从题目的例子中可以看出,根节点在最后,最下面一层的节点在最前面,都是从左往右的顺序,那么反过来看,[1,4,2,3,6,5],根节点被摆在了第一位,第二层的节点4从右边换到了左边,在左边的3换到了右边,第三层的节点也是如此。那么我们可以直接使用栈,从根节点开始入栈,然后根节点第一个出栈,接着是第二层的第一个节点3入栈,然后是2入栈,最后是4入栈,进入第二次循环,首先出栈的是4,然后是3,最后是3,并且同时也将第三层的节点入栈了。最后我们将拿到的结果反转即可,借助集合工具类来完成。

    /*
    // Definition for a Node.
    class Node {
        public int val;
        public List<Node> children;
    
        public Node() {}
    
        public Node(int _val,List<Node> _children) {
            val = _val;
            children = _children;
        }
    };
    */
    class Solution {
        public List<Integer> postorder(Node root) {
            if (root == null) {
                return new ArrayList<Integer>();
            }
            List<Integer> list = new ArrayList<Integer>();
            Stack<Node> stack = new Stack<Node>();
            stack.push(root);
            while (!stack.isEmpty()) {
                Node temp = stack.pop();
                list.add(temp.val);
                if (temp.children != null) {
                    for (Node n : temp.children) {
                        stack.push(n);
                    }
                }
            }
            Collections.reverse(list);
            return list;
        }
    }
    

    04 第三种解法

    针对上面的第二种解法,我们也可以不必反转list,二是使用LinkedList来存节点值,借助其addFirst方法,始终把节点值存入第一位。

    /*
    // Definition for a Node.
    class Node {
        public int val;
        public List<Node> children;
    
        public Node() {}
    
        public Node(int _val,List<Node> _children) {
            val = _val;
            children = _children;
        }
    };
    */
    class Solution {
        public List<Integer> postorder(Node root) {
            if (root == null) {
                return new LinkedList<Integer>();
            }
            LinkedList<Integer> list = new LinkedList<Integer>();
            Stack<Node> stack = new Stack<Node>();
            stack.push(root);
            while (!stack.isEmpty()) {
                Node temp = stack.pop();
                list.addFirst(temp.val);
                if (temp.children != null) {
                    for (Node n : temp.children) {
                        stack.push(n);
                    }
                }
            }
            return list;
        }
    }
    

    05 第四种解法

    使用两个栈。第一个栈正常的做入栈出栈操作,从根节点开始,第二个栈在循环内部只做入栈操作,使得根节点被压到了栈底部,而最后一个出栈的节点被压到了第二个栈的栈顶,此时再对第二个栈进行出栈操作,就实现了后序遍历。

    /*
    // Definition for a Node.
    class Node {
        public int val;
        public List<Node> children;
    
        public Node() {}
    
        public Node(int _val,List<Node> _children) {
            val = _val;
            children = _children;
        }
    };
    */
    class Solution {
        public List<Integer> postorder(Node root) {
            if (root == null) {
                return new ArrayList<Integer>();
            }
            List<Integer> list = new ArrayList<Integer>();
            Stack<Node> stack = new Stack<Node>();
            Stack<Node> stack2 = new Stack<Node>();
            stack.push(root);
            while (!stack.isEmpty()) {
                Node temp = stack.pop();
                stack2.push(temp);
                if (temp.children != null) {
                    for (Node n : temp.children) {
                        stack.push(n);
                    }
                }
            }
            while (!stack2.isEmpty()) {
                list.add(stack2.pop().val);
            }
            return list;
        }
    }
    

    06 小结

    算法专题目前已日更超过四个月,算法题文章136+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

    以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

  • 相关阅读:
    自定义CoordinatorLayout Behavior 隐藏Footer View
    开发错误记录10: Butterknife8.1.0 提示NullPointerException空指针
    要练习的项目
    2016年GitHub 排名前 100 的安卓、iOS项目简介(收藏)
    Android应用崩溃后异常捕获并重启并写入日志
    使用过的第三方框架汇总
    Eclipse导入 appcompat,design兼容包
    沉浸式模式与沉浸式状态栏
    开发错误记录9:Application无法跳转到Activity
    Android获取图片资源的4种方式
  • 原文地址:https://www.cnblogs.com/xiaochuan94/p/10487263.html
Copyright © 2020-2023  润新知