代码随想录-44-144. 二叉树的前序遍历、44-94. 二叉树的中序遍历、45-145. 二叉树的后序遍历(非统一迭代法)

前言

在本科毕设结束后,我开始刷卡哥的“代码随想录”,每天一节。自己的总结笔记均会放在“算法刷题-代码随想录”该专栏下。
代码随想录此题链接

题目

1.递归的思想

思路(定义变量)

  • TreeNode 树节点的类
  • ArrayDeque 作为遍历栈:记录访问元素的顺序
  • 封装结果的List< Integer>:记录处理元素的顺序
  • 中序还需要一个树节点的类的遍历指针,因为中序处理元素遍历元素的顺序不相同。

通解思路

处理元素意为,将元素的按照顺序输出到List< Integer>中。

前序:处理元素的顺序和访问元素的顺序相同,访问当前元素时即把当前元素处理(即当前元素val加入到List< Integer>中),并按“右、左”的顺序将当前节点的孩子节点加入到ArrayDeque 遍历栈中。(因为遍历栈弹出
的顺序跟入栈的顺序正好相反,所以弹出的顺序希望是“左、右”,输入的顺序就得是“右、左”)
继续循环的条件是,只要栈不为空。

后序:前序输出的顺序是“中、左、右”;后序是“左、右、中”;
前序可以先将左右顺序更换,变成“中、右、左”,然后整体倒序,“左、右、中”,此时顺序即为后序的顺序。
继续循环的条件是,只要栈不为空。

中序:处理元素的顺序和访问元素的顺序不同。所以需要添加一个树节点类型的遍历指针,来指向当前所访问的树节点。
继续循环的条件也与前序后序不同:当前树节点类型指针指向不为空或者栈不为空
循环时只有两种情况,1.当前访问的节点不为空,则将当前节点加入栈中,并且指针移向他的左孩子;2.当前节点为空,说明之前加入栈(此时的栈顶元素)的树节点为此时需要处理的元素,即弹出栈顶元素,并将其的val输出到List< Integer>中,且继续让指针指向他的右孩子。

2. 本题思路分析:

3. 算法实现

  • 代码:
    统一的树节点类
public class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
     TreeNode() {}
     TreeNode(int val) { this.val = val; }
     TreeNode(int val, TreeNode left, TreeNode right) {
         this.val = val;
         this.left = left;
         this.right = right;
     }
}

前序

public List<Integer> preorderTraversal(TreeNode root) {        
    //迭代法
    List<Integer> result = new ArrayList<>();
    if(root == null) return result;
    Deque<TreeNode> stack = new ArrayDeque<>();
    stack.push(root);
    while(!stack.isEmpty()){
        TreeNode cur = stack.pop();
        result.add(cur.val);
        if(cur.right != null){
            stack.push(cur.right);
        }
        if(cur.left != null){
            stack.push(cur.left);
        }
    }
    return result;
}

中序

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList();
    Deque<TreeNode> stack = new ArrayDeque();
    TreeNode cur = root;
    while(!stack.isEmpty() || cur != null){
        if(cur != null){
            stack.push(cur);
            cur = cur.left;
        }else{
            cur = stack.pop();
            result.add(cur.val);
            cur = cur.right;
        }
    }
    return result;
}

后序

public List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList();
    if(root == null){
        return result;
    }
    Deque<TreeNode> stack = new ArrayDeque();
    stack.push(root);
    TreeNode cur = new TreeNode();
    while(!stack.isEmpty()){
        cur = stack.pop();
        result.add(cur.val);
        if(cur.left != null){
            stack.push(cur.left);
        }
        if(cur.right != null){
            stack.push(cur.right);
        }
    }
    Collections.reverse(result);
    return result;
}

4. pop函数的算法复杂度

树的节点数量为n
空间复杂度:O(n)
时间复杂度:O(n)

5. 算法坑点

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值