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

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

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

相关文章
|
3天前
|
算法
分享一些提高二叉树遍历算法效率的代码示例
这只是简单的示例代码,实际应用中可能还需要根据具体需求进行更多的优化和处理。你可以根据自己的需求对代码进行修改和扩展。
|
6天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
42 8
|
6天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
29 7
|
6天前
|
存储 缓存 算法
如何提高二叉树遍历算法的效率?
选择合适的遍历算法,如按层次遍历树时使用广度优先搜索(BFS),中序遍历二叉搜索树以获得有序序列。优化数据结构,如使用线索二叉树减少空指针判断,自定义节点类增加辅助信息。利用递归与非递归的特点,避免栈溢出问题。多线程并行遍历提高速度,注意线程安全。缓存中间结果,避免重复计算。预先计算并存储信息,提高遍历效率。综合运用这些方法,提高二叉树遍历算法的效率。
21 5
|
9天前
|
机器学习/深度学习 JSON 算法
二叉树遍历算法的应用场景有哪些?
【10月更文挑战第29天】二叉树遍历算法作为一种基础而重要的算法,在许多领域都有着不可或缺的应用,它为解决各种复杂的问题提供了有效的手段和思路。随着计算机科学的不断发展,二叉树遍历算法也在不断地被优化和扩展,以适应新的应用场景和需求。
19 0
|
14天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
14天前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
26天前
|
监控 算法 数据安全/隐私保护
基于三帧差算法的运动目标检测系统FPGA实现,包含testbench和MATLAB辅助验证程序
本项目展示了基于FPGA与MATLAB实现的三帧差算法运动目标检测。使用Vivado 2019.2和MATLAB 2022a开发环境,通过对比连续三帧图像的像素值变化,有效识别运动区域。项目包括完整无水印的运行效果预览、详细中文注释的代码及操作步骤视频,适合学习和研究。
|
1月前
|
存储 缓存 算法
经典算法之链表篇(三)
经典算法之链表篇(三)
|
5月前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表