【算法训练-二叉树 七】【二叉搜索树】验证二叉搜索树、将二叉搜索树转为排序的双向循环链表

简介: 【算法训练-二叉树 七】【二叉搜索树】验证二叉搜索树、将二叉搜索树转为排序的双向循环链表

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【】,使用【】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为:目标公司+最近一年+出现频率排序,由高到低的去牛客TOP101去找,只有两个地方都出现过才做这道题(CodeTop本身汇聚了LeetCode的来源),确保刷的题都是高频要面试考的题。

明确目标题后,附上题目链接,后期可以依据解题思路反复快速练习,题目按照题干的基本数据结构分类,且每个分类的第一篇必定是对基础数据结构的介绍

验证二叉搜索树【MID】

中序遍历递归验证二叉搜索树

题干

解题思路

二叉搜索树的特性就是中序遍历是递增序,既然是判断是否是二叉搜索树,那我们可以使用中序递归遍历。只要之前的节点是二叉树搜索树,那么如果当前的节点小于上一个节点值那么就可以向下判断

代码实现

给出代码实现基本档案

基本数据结构二叉树

辅助数据结构

算法递归,DFS

技巧

其中数据结构、算法和技巧分别来自:

  • 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
  • 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
  • 技巧:双指针、滑动窗口、中心扩散

当然包括但不限于以上

import java.util.*;
/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */
public class Solution {
    private int maxValue = Integer.MIN_VALUE;
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @return bool布尔型
     */
    public boolean isValidBST (TreeNode root) {
        if (root == null) {
            return false;
        }
        return dfsCheck(root);
    }
    private boolean dfsCheck(TreeNode root) {
        // 1 判断的递归终止条件,到达叶子节点
        if (root == null) {
            return true;
        }
        // 2 如果左子树不满足条件,返回false
        if (!dfsCheck(root.left)) {
            return false;
        }
        // 如果当前值小于历史最大值,则不满足,返回false
        if (root.val < maxValue) {
            return false;
        }
        // 更新历史最大值为当前值
        maxValue = root.val;
        // 3 返回右子树的结果
        return dfsCheck(root.right);
    }
}

复杂度分析

时间复杂度:O(n),其中n为二叉树的节点数,遍历整棵二叉树

空间复杂度:O(n),最坏情况下,二叉树化为链表,递归栈深度最大为n

将二叉搜索树转为排序的双向循环链表【MID】

数据结构考察,二叉搜索树和双向链表互转

题干

解题思路

本文解法基于性质:二叉搜索树的中序遍历为递增序列 。 将 二叉搜索树 转换成一个 “排序的循环双向链表” ,其中包含三个要素:

  • 排序链表: 节点应从小到大排序,因此应使用 中序遍历 “从小到大”访问树的节点。
  • 双向链表: 在构建相邻节点的引用关系时,设前驱节点 pre 和当前节点 cur ,不仅应构建 pre.right = cur ,也应构建 cur.left = pre
  • 循环链表: 设链表头节点 head 和尾节点 tail ,则应构建 head.left = tailtail.right = head

整体如下图所示

中序遍历 为对二叉树作 “左、根、右” 顺序遍历算法流程:dfs(cur): 递归法中序遍历;

  • 终止条件: 当节点 cur 为空,代表越过叶节点,直接返回;
  • 递归左子树,即 dfs(cur.left) ; 构建链表:当 pre 为空时: 代表正在访问链表头节点,记为 head ;当 pre 不为空时: 修改双向节点引用,即 pre.right = cur , cur.left = pre ;保存 cur : 更新 pre = cur ,即节点 cur 是后继节点的 pre ;
  • 递归右子树,即 dfs(cur.right) ;处理过程同上
    treeToDoublyList(root):

特例处理: 若节点 root 为空,则直接返回;初始化: 空节点 pre ;转化为双向链表: 调用 dfs(root) ;构建循环链表: 中序遍历完成后,head 指向头节点, pre 指向尾节点,因此修改 head 和 pre 的双向节点引用即可;返回值: 返回链表的头节点 head 即可;

代码实现

给出代码实现基本档案

基本数据结构二叉树

辅助数据结构

算法递归,DFS

技巧

其中数据结构、算法和技巧分别来自:

  • 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
  • 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
  • 技巧:双指针、滑动窗口、中心扩散

当然包括但不限于以上

/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;
    public Node() {}
    public Node(int _val) {
        val = _val;
    }
    public Node(int _val,Node _left,Node _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
    // 1 定义头节点和前置节点
    private Node head;
    private Node pre;
    public Node treeToDoublyList(Node root) {
        if (root == null) {
            return null;
        }
        // 1 递归处理节点关系
        dfsGen(root);
        // 2 绑定头尾节点
        // 初始化头尾节点相互指向:尾节点的下一个是头节点
        pre.right = head;
        // 初始化头尾节点相互指向:头节点的上一个是尾节点
        head.left = pre;
        // 3 返回头节点
        return head;
    }
    private void dfsGen(Node cur) {
        if (cur == null) {
            return;
        }
        // 1 中序遍历,先处理左子树
        dfsGen(cur.left);
        if (pre == null) {
            // 记录头节点位置
            head = cur;
        } else {
            // 本级任务:pre节点与cur节点进行绑定
            pre.right = cur;
            cur.left = pre;
        }
        pre = cur;
        // 3 中序遍历,最后处理右子树
        dfsGen(cur.right);
    }
}

复杂度分析

时间复杂度:O(n),其中n为二叉树的节点数,遍历整棵二叉树

空间复杂度:O(n),最坏情况下,二叉树化为链表,递归栈深度最大为n

拓展知识:二叉搜索树

二叉搜索树(Binary Search Tree,简称BST)是一种二叉树的形式,它具有一些特殊的性质,使得它在存储和检索数据方面非常高效。BST中的每个节点都包含一个值,而且对于每个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都大于该节点的值。这个性质使得在BST中查找、插入和删除操作都可以在平均情况下在**O(log n)**的时间内完成,其中n是BST中节点的数量。

以下是一些BST的基本性质和操作:

  1. 查找:要查找BST中的一个特定值,可以从根节点开始,比较目标值与当前节点的值。如果目标值小于当前节点的值,就在左子树中继续查找;如果大于当前节点的值,就在右子树中查找。如果找到目标值,操作成功;否则,继续向下查找,直到找到目标值或者达到叶子节点。
  2. 插入:要插入一个新值到BST中,首先执行查找操作,找到插入位置。然后,在插入位置创建一个新节点,将新值赋给该节点,并将其连接到树中的合适位置。插入操作确保BST的性质仍然成立。
  3. 删除:要删除BST中的一个值,首先执行查找操作,找到要删除的节点。然后,根据节点的子树情况执行不同的操作:如果节点是叶子节点,直接删除它;如果节点有一个子节点,将子节点提升到删除节点的位置;如果节点有两个子节点,可以选择用其前驱节点或后继节点替代,然后递归地删除前驱或后继节点。

BST的性能取决于树的结构,最好的情况是平衡二叉搜索树(Balanced BST),其中左子树和右子树的高度大致相等,这样可以确保查找、插入和删除等操作都能在O(log n)的时间内完成。常见的平衡BST包括AVL树和红黑树。

然而,如果BST不平衡,最坏情况下操作的时间复杂度可能会退化到O(n),例如当BST退化成一个链表时。因此,在实际应用中,通常需要采取一些方法来维护BST的平衡性,以确保高效的性能。

相关文章
|
10天前
|
算法
分享一些提高二叉树遍历算法效率的代码示例
这只是简单的示例代码,实际应用中可能还需要根据具体需求进行更多的优化和处理。你可以根据自己的需求对代码进行修改和扩展。
|
13天前
|
存储 缓存 算法
如何提高二叉树遍历算法的效率?
选择合适的遍历算法,如按层次遍历树时使用广度优先搜索(BFS),中序遍历二叉搜索树以获得有序序列。优化数据结构,如使用线索二叉树减少空指针判断,自定义节点类增加辅助信息。利用递归与非递归的特点,避免栈溢出问题。多线程并行遍历提高速度,注意线程安全。缓存中间结果,避免重复计算。预先计算并存储信息,提高遍历效率。综合运用这些方法,提高二叉树遍历算法的效率。
35 5
|
16天前
|
机器学习/深度学习 JSON 算法
二叉树遍历算法的应用场景有哪些?
【10月更文挑战第29天】二叉树遍历算法作为一种基础而重要的算法,在许多领域都有着不可或缺的应用,它为解决各种复杂的问题提供了有效的手段和思路。随着计算机科学的不断发展,二叉树遍历算法也在不断地被优化和扩展,以适应新的应用场景和需求。
24 0
|
20天前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
1月前
|
监控 算法 数据安全/隐私保护
基于三帧差算法的运动目标检测系统FPGA实现,包含testbench和MATLAB辅助验证程序
本项目展示了基于FPGA与MATLAB实现的三帧差算法运动目标检测。使用Vivado 2019.2和MATLAB 2022a开发环境,通过对比连续三帧图像的像素值变化,有效识别运动区域。项目包括完整无水印的运行效果预览、详细中文注释的代码及操作步骤视频,适合学习和研究。
|
28天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
13天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
|
14天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。
|
15天前
|
存储 算法 决策智能
基于免疫算法的TSP问题求解matlab仿真
旅行商问题(TSP)是一个经典的组合优化问题,目标是寻找经过每个城市恰好一次并返回起点的最短回路。本文介绍了一种基于免疫算法(IA)的解决方案,该算法模拟生物免疫系统的运作机制,通过克隆选择、变异和免疫记忆等步骤,有效解决了TSP问题。程序使用MATLAB 2022a版本运行,展示了良好的优化效果。
|
14天前
|
机器学习/深度学习 算法 芯片
基于GSP工具箱的NILM算法matlab仿真
基于GSP工具箱的NILM算法Matlab仿真,利用图信号处理技术解析家庭或建筑内各电器的独立功耗。GSPBox通过图的节点、边和权重矩阵表示电气系统,实现对未知数据的有效分类。系统使用MATLAB2022a版本,通过滤波或分解技术从全局能耗信号中提取子设备的功耗信息。