leetcode 145+590 二叉树后序遍历(iterative)(附589,144,94)

前序遍历与后序遍历非递归实现思路:

前序遍历的顺序是:根——左——右。

后序遍历的顺序是:左——右——根。

从上面可以看出,两者的差异仅仅是根的位置一个在最前面,一个在最后面。而遍历函数的传入参数是根(这点及其重要,也解释了为何后面前序后序遍历有些实现是近似的)。

现在封装一个LinkedList:a存储最终的输出顺序。封装另一个LinkedList:b存储要被处理的节点。

传入的是根,由于两种顺序根的位置固定,故从根就可以开始处理。

重点:制定方案,决定从b的哪端开始处理节点,从a的哪端开始插入节点值。之后一直保持这个顺序即可。

如:前序遍历根在最前面,a端最先插入的值是根值,故之后应从尾部插入

后序遍历根在最后面,a端最先插入的值是根值,故之后应从头部插入

举例前序遍历:

b:  根

a:空

b:  根从尾部弹出,压入右、左

a:从尾部添加弹出节点值

反复即可

题目描述

145. Binary Tree Postorder Traversal

Given a binary tree, return the postorder traversal of its nodes' values.

Example:

Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [3,2,1]
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
    LinkedList<TreeNode> stack = new LinkedList<>();
    LinkedList<Integer> output = new LinkedList<>();
    if (root == null) {
      return output;
    }

    stack.add(root);
    while (!stack.isEmpty()) {
      TreeNode node = stack.pollLast();
      output.addFirst(node.val);
      if (node.left != null) {
        stack.add(node.left);
      }
      if (node.right != null) {
        stack.add(node.right);
      }
    }
    return output;
  }
}

590. N-ary Tree Postorder Traversal

Given an n-ary tree, return the postorder traversal of its nodes' values.

For example, given a 3-ary tree:

 

Return its postorder traversal as: [5,6,3,2,4,1].

class Solution {
    public List<Integer> postorder(Node root) {
        LinkedList<Node> stack= new LinkedList<>();
        LinkedList<Integer> output= new LinkedList<>();
        if(root==null)
            return output;
        stack.add(root);
        while(!stack.isEmpty()){
            Node tmp= stack.pollLast();
            output.addFirst(tmp.val);
                for(Node n: tmp.children){
                    if(n!=null)
                         stack.add(n);
                }
                   
        }
        return output;
    }
    
}

145与590两道题只有树节点的构造稍微不同,实现原理都是相同的。要求不用递归,迭代做、

下图是solution解释中的图,非原创

通过上图可发现:

BFS:从上至下,从左至右

DFS:左右根有三种排列方式

144. Binary Tree Preorder Traversal

Given a binary tree, return the preorder traversal of its nodes' values.

Example:

Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [1,2,3]
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        LinkedList<TreeNode> stack= new LinkedList<>();
        LinkedList<Integer> output= new LinkedList<>();
        if(root==null)
            return output;
        stack.add(root);
        while(!stack.isEmpty()){
            TreeNode tmp= stack.pollLast();
            output.addLast(tmp.val);
            if(tmp.right!=null){
                stack.addLast(tmp.right);
            }
            if(tmp.left!=null){
                stack.addLast(tmp.left);
            }
        }
        return output;
    }
}

589. N-ary Tree Preorder Traversal

Given an n-ary tree, return the preorder traversal of its nodes' values.

For example, given a 3-ary tree:

 

 

Return its preorder traversal as: [1,3,5,6,2,4].

class Solution {
    public List<Integer> preorder(Node root) {
        LinkedList<Node> stack= new LinkedList<>();
        LinkedList<Integer> output= new LinkedList<>();
        if(root==null)
            return output;
        stack.add(root);
        while(!stack.isEmpty()){
            Node tmp= stack.pollLast();
            output.addLast(tmp.val);
            int index= tmp.children.size()-1;
            for(;index>=0;index--){
                Node chil= tmp.children.get(index);
                if(chil!=null)  stack.addLast(chil);
            }
        }
        return output;
    }
}

 

94. Binary Tree Inorder Traversal

Given a binary tree, return the inorder traversal of its nodes' values.

Example:

Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [1,3,2]
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        LinkedList<TreeNode> stack= new LinkedList<>();
        LinkedList<Integer> output= new LinkedList<>();
        if(root==null)
            return output;
        stack.add(root);
        //cur表示下一个可能被处理的节点,对于根而言,是左孩子
        TreeNode cur= root.left;
        while(cur!=null || !stack.isEmpty()){
            //对于每一个可能被处理的节点,要先处理他们的左孩子
            while(cur!=null){
                stack.addLast(cur);
                cur= cur.left;
            }
            cur= stack.pollLast();
            output.addLast(cur.val);
            //根已经输出,下一个可能的被处理节点是右孩子
            cur= cur.right;
        }
        return output;
    }
}

下面这种中序遍历的方式是错误的,虽然逻辑上乍一看没有什么问题!!!!!如果一定要这么写,一定要判重,有没有加入过它的左孩子 

public List<Integer> inorderTraversal(TreeNode root) {
        //一种常见的错误写法,peek顶端查看有无左孩子,有的话就加入
        //漏洞:可能循环压入多次左孩子导致超时
        LinkedList<TreeNode> stack= new LinkedList<>();
        LinkedList<Integer> output= new LinkedList<>();
        if(root==null)
            return output;
        stack.add(root);
        TreeNode cur= root.left;
        while(cur!=null || !stack.isEmpty()){
            while(cur!=null){
                stack.addLast(cur);
                cur= cur.left;
            }
            cur= stack.pollLast();
            output.addLast(cur.val);
            cur= cur.right;
        }
        return output;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值