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

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

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

相关文章
|
存储 算法 Java
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
529 10
 算法系列之数据结构-二叉树
分享一些提高二叉树遍历算法效率的代码示例
这只是简单的示例代码,实际应用中可能还需要根据具体需求进行更多的优化和处理。你可以根据自己的需求对代码进行修改和扩展。
478 64
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
770 3
|
存储 算法 Python
文件管理系统中基于 Python 语言的二叉树查找算法探秘
在数字化时代,文件管理系统至关重要。本文探讨了二叉树查找算法在文件管理中的应用,并通过Python代码展示了其实现过程。二叉树是一种非线性数据结构,每个节点最多有两个子节点。通过文件名的字典序构建和查找二叉树,能高效地管理和检索文件。相较于顺序查找,二叉树查找每次比较可排除一半子树,极大提升了查找效率,尤其适用于海量文件管理。Python代码示例包括定义节点类、插入和查找函数,展示了如何快速定位目标文件。二叉树查找算法为文件管理系统的优化提供了有效途径。
326 5
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
10月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
798 0
|
10月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
499 2
|
11月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
406 3
|
10月前
|
机器学习/深度学习 算法 机器人
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
417 8
|
10月前
|
机器学习/深度学习 算法 自动驾驶
基于导向滤波的暗通道去雾算法在灰度与彩色图像可见度复原中的研究(Matlab代码实现)
基于导向滤波的暗通道去雾算法在灰度与彩色图像可见度复原中的研究(Matlab代码实现)
473 8