LeetCode 590. N 叉树的后序遍历

88 阅读1分钟

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

给定一个 n 叉树的根节点 root ,返回 其节点值的 后序遍历 。 n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

N叉树的后序遍历,对比二叉树的后序遍历很容易就能够写出来,代码如下:

public List<Integer> postorder(Node root) {
    List<Integer> result = new ArrayList();
    if(root == null){
        return result;
    }
    // 遍历所有孩子结点
    for(int i = 0;i < root.children.size();++i){
        result.addAll(postorder(root.children.get(i)));
    }
    // 最后访问根结点
    result.add(root.val);
    return result;
}

对于非递归的写法,我们仍然使用一个栈结构来实现后序遍历的过程,后序遍历的访问顺序是先访问孩子节点,再访问根结点,所以要将孩子节点先入栈,当所有孩子均入栈后再执行遍历操作。

举个例子:

image.png

对于这样的一棵树,我们首先将根节点1入栈,然后执行一个peek操作,该操作会返回栈顶的元素,但是不会删除它,返回了根节点1后,将其孩子全部入栈,此时的栈:[3,2,4,1];再对栈进行peek操作,此时会返回栈顶元素3,再将节点3的所有孩子入栈,此时的栈:[5,6,3,2,4,1];继续peek操作,返回栈顶元素5,节点5没有孩子,那么就真正地将节点5出栈,此时的栈:[6,3,2,4,1]

以上过程出现了一个问题,就是各个节点之间的关系已经搞不清楚了,谁是谁的孩子节点,谁是谁的父亲节点,由此,我们需要借助一个标志位来分隔一下节点之间的关系。

改进一下思路,当根节点peek操作时,向栈中压入一个null,再将根节点的所有孩子入栈:

[3,2,4,null,1]

当节点3peek操作时,也向栈中压入一个null,再将孩子入栈:

[5,6,null,3,2,4,null,1]

此时当节点5peek操作时,因为没有孩子,所以只会压入一个null:

[null,5,6,null,3,2,4,null,1]

而当null执行peek操作时,我们就清楚了到这一步已经没有孩子节点了,所以直接将null弹出,并继续弹出下一个节点5:

[6,null,3,2,4,null,1]

重复此项操作,对节点6进行peek操作时,就需要观察是否有孩子节点,没有,直接压入null:

[null,6,null,3,2,4,null,1]

继续弹栈,为null,直接弹出,并弹出下一个节点6,继续弹出null,并弹出下一个节点3,以此类推。

不难发现,此时便做到了先访问节点的孩子节点,再访问节点的遍历顺序。

代码如下:

public List<Integer> postorder(Node root) {
    List<Integer> result = new ArrayList();
    if(root == null){
        return result;
    }
    Stack<Node> stack = new Stack<>();
    // 根节点入栈
    stack.push(root);
    Node node;
    while(!stack.isEmpty()){
        // 得到栈顶元素
        node = stack.peek();
        // 若栈顶元素为空,说明子树遍历到头了
        if(node == null){
            // 弹出null标志
            stack.pop();
            // 弹出节点
            node = stack.pop();
            result.add(node.val);
            // 重复操作
            continue;
        }
        // 存入标志位
        stack.push(null);
        // 将所有孩子节点入栈
        for(int i = node.children.size() - 1;i >= 0;--i){
            stack.push(node.children.get(i));
        }
    }
    return result;
}

此题得解。