【算法训练营Day11】二叉树part1

文章目录

理论基础

二叉树在结构上的两个常用类型:

  • 满二叉树
  • 完全二叉树

在功能应用上的比较常用的有:

  • 二叉搜索树: 节点有权值、遵循"左小右大"
  • 平衡二叉搜索树(AVL树): 在二叉树的基础上增添了一个特性,左右子树高度差不超过1

二叉树的存储方式

  • 顺序存储:使用数组,在内存中连续分布

  • 链式存储:使用指针,在内存中离散分布

二叉树的遍历方式

  • 深度优先遍历(可借助栈)
    • 前序遍历(递归法,迭代法)
    • 中序遍历(递归法,迭代法)
    • 后序遍历(递归法,迭代法)
  • 广度优先遍历(可借助队列)
    • 层序遍历(迭代法)

二叉树的定义

java 复制代码
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;
    }
}

二叉树的递归遍历

前序遍历

题目链接:144. 二叉树的前序遍历

java 复制代码
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        preRead(root,result);
        return result;
    }

    public void preRead(TreeNode node,List<Integer> list){
        if(node == null) return;
        list.add(node.val);
        preRead(node.left,list);
        preRead(node.right,list);
    }
}

中序遍历

题目链接:94. 二叉树的中序遍历

java 复制代码
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        inRead(root,result);
        return result;
    }

    public void inRead(TreeNode node,List<Integer> list){
        if(node == null) return;
        inRead(node.left,list);
        list.add(node.val);
        inRead(node.right,list);
    }
}

后序遍历

题目链接:145. 二叉树的后序遍历

java 复制代码
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        postRead(root,result);
        return result;
    }

    public void postRead(TreeNode node,List<Integer> list){
        if(node == null) return;
        postRead(node.left,list);
        postRead(node.right,list);
        list.add(node.val);
    }
}

总结

递归算法的三要素

  • 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。

    • 通过"参数传递"自顶向下传递信息
    • 通过"函数返回值"自底向上传递信息
    • 使用全局变量,在各级函数间共享信息
  • 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。

  • 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

二叉树的层序遍历

基础层序遍历

题目链接:102. 二叉树的层序遍历

层序遍历的逻辑:

  • 初始化一个队列
  • 首先将根节点放入队列中
  • 接下来循环往复如下操作
    • 弹出队头元素
    • 将弹出元素的左右节点入队

这个题的要求在层序遍历的基础上增加了分层的逻辑,解题逻辑如下:

  • 在层序遍历的基础上
  • 我们再初始化一个队列temp(主队列命名为queue)
  • 我们在queue中把当前层的元素弹出时,并不立马将其左右元素入队queue,而是将其添加到temp队列中
  • 当queue中所有元素弹完之后,再将temp的元素全部添加到queue中
  • 这样就达成了queue中永远是二叉树中每层的所有元素

解题逻辑:

java 复制代码
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<>();
        Deque<TreeNode> queue = new ArrayDeque<>();
        if(root == null) return new ArrayList<List<Integer>>();
        queue.add(root);
        while(!queue.isEmpty()) {
            List<Integer> part = new ArrayList<>();
            Deque<TreeNode> temp = new ArrayDeque<>();
            while (!queue.isEmpty()) {
                TreeNode node = queue.poll();
                part.add(node.val);
                if(node.left != null) temp.add(node.left);
                if(node.right != null) temp.add(node.right);
            }
            result.add(part);
            while(!temp.isEmpty()) queue.add(temp.poll());
        }
        return result;
    }
}

这个地方可以进一步改进:

  • 无需使用新的队列来临时存储一层的元素
  • 而是可以直接用一个变量界定一层的元素个数
java 复制代码
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new LinkedList<>();
        Deque<TreeNode> queue = new ArrayDeque<>();
        if(root == null) return new ArrayList<List<Integer>>();
        queue.add(root);
        while(!queue.isEmpty()) {
            List<Integer> part = new LinkedList<>();
            int count = queue.size();
            while (count > 0) {
                TreeNode node = queue.poll();
                part.add(node.val);
                if(node.left != null) queue.add(node.left);
                if(node.right != null) queue.add(node.right);
                count--;
            }
            result.add(part);
        }
        return result;
    }
}

二叉树的右视图

题目链接:199. 二叉树的右视图

解题逻辑:

  • 在前一题的基础上只将每一层的最后一个元素添加到结果集中就可以
  • 我们通过控制每层的长度变量,当变量为1的时候才添加到结果集中
java 复制代码
class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> result = new LinkedList<>();
        Deque<TreeNode> queue = new ArrayDeque<>();
        if(root == null) return new ArrayList<Integer>();
        queue.add(root);
        while(!queue.isEmpty()) {
            int count = queue.size();
            while (count > 0) {
                TreeNode node = queue.poll();
                if(count == 1) result.add(node.val);
                if(node.left != null) queue.add(node.left);
                if(node.right != null) queue.add(node.right);
                count--;
            }
        }
        return result;
    }
}
相关推荐
CoovallyAIHub13 分钟前
OpenClaw一脚踩碎传统CV?机器终于不再只是看世界
深度学习·算法·计算机视觉
CoovallyAIHub29 分钟前
仅凭单目相机实现3D锥桶定位?UNet-RKNet破解自动驾驶锥桶检测难题
深度学习·算法·计算机视觉
zone773930 分钟前
002:RAG 入门-LangChain 读取文本
后端·算法·面试
得物技术1 小时前
得物社区搜推公式融合调参框架-加乘树3.0实战
算法
会员源码网20 小时前
使用`mysql_*`废弃函数(PHP7+完全移除,导致代码无法运行)
后端·算法
木心月转码ing21 小时前
Hot100-Day10-T438T438找到字符串中所有字母异位词
算法
HelloReader1 天前
Wi-Fi CSI 感知技术用无线信号“看见“室内的人
算法
颜酱1 天前
二叉树分解问题思路解题模式
javascript·后端·算法
qianpeng8971 天前
水声匹配场定位原理及实验
算法
董董灿是个攻城狮2 天前
AI视觉连载8:传统 CV 之边缘检测
算法