• 死磕二叉树(一)


    定义

    二叉树是每个结点最多有两个子树的树结构。

                     3
                    / 
                   4   5
                  / 
                 1   2
    

    因为二叉树的左右子树都具有类似的结构,二叉树的题目往往和递归是关联的。

    从二叉树的遍历谈起

    遍历二叉树的每一个点,通常有三种方式,中序,前序,后序的方式,对应上图的树来说,结果是:

    3 4 1 2 5 // 前序
    1 4 2 3 5 // 中序
    1 2 4 5 3 // 后序
    

    前、后、中都是相对于根节点的位置来定义的。

    首先来看:

    94. 二叉树的中序遍历

    深度优先

    通过递归的方式很容易构造,关键在于如何选出递归结束的条件,比如当前节点是空值时,需要return

    方法一:

    class Solution {
        List<Integer> list = new ArrayList<>();
        public List<Integer> inorderTraversal(TreeNode root) {
            helper(root);
            return list;
        }
        
        void helper(TreeNode root){
            if(root == null) return;
            else {
                if(root.left != null) helper(root.left);
                list.add(root.val);
                if(root.right != null) helper(root.right);
            }
        }
    }
    

    方法二:

    除了递归的方式,还有迭代法,迭代中序遍历时,需要借助一个栈,栈的功能是存储上一个节点,好让处理完左子树的时候,可以回头访问根节点,根据这个思路,我们可以在访问开始前沿着左子树一路访问到null,然后再访问上一个节点(此时可以看成根节点),最后再访问右节点:

    class Solution {
        public List<Integer> inorderTraversal2(TreeNode root){
            List<Integer> list = new ArrayList<>();
            Stack<TreeNode> stack = new Stack<>();
    
            while (root != null || !stack.isEmpty()){
                if(root != null){
                    stack.add(root);
                    root = root.left;
                } else {
                    root = stack.pop();
                    list.add(root.val);
                    root = root.right;
                }
            }
            return list;
        }
    }
    

    144. 二叉树的前序遍历

    有了中序遍历的基础,前序遍历的递归形式可以很容易的写出来:

    方法一:

    class Solution {
        List<Integer> list = new ArrayList<>();
        public List<Integer> inorderTraversal(TreeNode root) {
            helper(root);
            return list;
        }
        
        void helper(TreeNode root){
            if(root == null) return;
            else {
                list.add(root.val);
                if(root.left != null) helper(root.left);
                if(root.right != null) helper(root.right);
            }
        }
    }
    

    方法二:

    使用迭代法依然时要借助一个栈来实现,这里栈的功能和中序遍历类似,都是要存储上一个节点,便于访问完左子树后再访问右子树。不同的是,访问下一个左节点之前,就需要把节点的值保存到结果中去:

    class Solution {
        public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> res = new ArrayList<>();
            Stack<TreeNode> stack = new Stack<>();
            
            while (!stack.isEmpty() || root != null){
                if(root != null){
                    stack.add(root);
                    res.add(root.val);
                    root = root.left;
                }else{
                    root = stack.pop();
                    root = root.right;
                }
            }
    
            return res;
        }
    }
    

    145. 二叉树的后序遍历

    前序遍历和后序遍历之间的的关系:

    前序遍历顺序为:根 -> 左 -> 右

    后序遍历顺序为:左 -> 右 -> 根

    前序遍历的时候,每个节点的值都会插入到结果链表的尾部res.add(root.val)

    如果每次都选择插入到结果链表的头部,那么遍历顺序会变为:右 -> 左 -> 根

    此时转换一下左右子树的先后顺序,就得到我们想要的结果:左 -> 右 -> 根

    迭代法:

    class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
            LinkedList<Integer> res = new LinkedList<Integer>();
            Stack<TreeNode> stack = new Stack<>();
            
            while (!stack.isEmpty() || root != null){
                if(root != null){
                    stack.add(root);
                    res.addFirst(root.val);
                    root = root.right;
                }else{
                    root = stack.pop();
                    root = root.left;
                }
            }
    
            return res;
        }
    }
    

  • 相关阅读:
    python爬取糗事百科段子
    python爬虫-韩寒新浪博客博文
    python-函数
    Python-列表
    Linux学习笔记001——win下安装Linux虚拟机
    python爬虫-正则表达式
    IIS使用十大原则,(IIS过期时间,IIS缓存设置) 【转载】
    在mysql 中两种锁定问题
    php 迭代器与和生成器
    DBCP连接池使用问题
  • 原文地址:https://www.cnblogs.com/punnpkin/p/13574323.html
Copyright © 2020-2023  润新知