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

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

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇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的平衡性,以确保高效的性能。

目录
打赏
0
0
0
0
33
分享
相关文章
基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
|
19天前
|
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
45 9
 算法系列之数据结构-二叉树
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
96 29
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
121 25
|
3月前
|
Go 语言中实现 RSA 加解密、签名验证算法
随着互联网的发展,安全需求日益增长。非对称加密算法RSA成为密码学中的重要代表。本文介绍如何使用Go语言和[forgoer/openssl](https://github.com/forgoer/openssl)库简化RSA加解密操作,包括秘钥生成、加解密及签名验证。该库还支持AES、DES等常用算法,安装简便,代码示例清晰易懂。
77 12
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
66 2
基于生物地理算法的MLP多层感知机优化matlab仿真
本程序基于生物地理算法(BBO)优化MLP多层感知机,通过MATLAB2022A实现随机数据点的趋势预测,并输出优化收敛曲线。BBO模拟物种在地理空间上的迁移、竞争与适应过程,以优化MLP的权重和偏置参数,提升预测性能。完整程序无水印,适用于机器学习和数据预测任务。
基于LSB最低有效位的音频水印嵌入提取算法FPGA实现,包含testbench和MATLAB对比
本项目展示了一种基于FPGA的音频水印算法,采用LSB(最低有效位)技术实现版权保护与数据追踪功能。使用Vivado2019.2和Matlab2022a开发,完整代码含中文注释及操作视频。算法通过修改音频采样点的最低有效位嵌入水印,人耳难以察觉变化。然而,面对滤波或压缩等攻击时,水印提取可能受影响。该项目运行效果无水印干扰,适合实时应用场景,核心逻辑简单高效,时间复杂度低。
基于GA遗传算法的拱桥静载试验车辆最优布载matlab仿真
本程序基于遗传算法(GA)实现拱桥静载试验车辆最优布载的MATLAB仿真,旨在自动化确定车辆位置以满足加载效率要求(0.95≤ηq≤1.05),目标是使ηq尽量接近1,同时减少车辆数量和布载耗时。程序在MATLAB 2022A版本下运行,展示了工况1至工况3的测试结果。通过优化模型,综合考虑车辆重量、位置、类型及车道占用等因素,确保桥梁关键部位承受最大荷载,从而有效评估桥梁性能。核心代码实现了迭代优化过程,并输出最优布载方案及相关参数。
基于MobileNet深度学习网络的活体人脸识别检测算法matlab仿真
本内容主要介绍一种基于MobileNet深度学习网络的活体人脸识别检测技术及MQAM调制类型识别方法。完整程序运行效果无水印,需使用Matlab2022a版本。核心代码包含详细中文注释与操作视频。理论概述中提到,传统人脸识别易受非活体攻击影响,而MobileNet通过轻量化的深度可分离卷积结构,在保证准确性的同时提升检测效率。活体人脸与非活体在纹理和光照上存在显著差异,MobileNet可有效提取人脸高级特征,为无线通信领域提供先进的调制类型识别方案。