目录

一、BST定义和性质

二、二叉搜索树中第K小的元素

三、把二叉搜索树转换为累加树

四、合法二叉搜索树

五、二叉搜索树中的搜索

六、二叉搜索树中的插入操作

七、在 BST 中删除一个数

八、不同的二叉搜索树

九、不同的二叉搜索树 II


一、BST定义和性质

定义:BST是一棵空树,或者具有以下性质的二叉树:

性质:

  • 若它的左子树不空,则左子树的所有节点值都小于根节点的值
  • 若它的右子树不空,则右子树的所有节点值都大于根节点的值
  • 左子树和右子树都是二叉搜索树

备注:BST中序遍历是升序序列

根据以上性质,下面介绍相关BST题型

二、二叉搜索树中第K小的元素

题目:给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

示例 1:

输入:root = [3,1,4,null,2], k = 1
输出:1
示例 2:

输入:root = [5,3,6,2,4,null,null,1], k = 3
输出:3

分析:

  • 根据BST中序遍历为升序序列,则该题进行中序遍历,遍历到第K个节点即可

示例代码:

int nRet = 0;
int nIndex = 0;
void help(TreeNode* root,int k)
{if (root == nullptr){return ;}if (root->left != nullptr){help(root->left,k);}nIndex++;if (k == nIndex){nRet = root->val;return ;}// vecNum.push_back(root->val);if (root->right != nullptr){help(root->right,k);}
}
int kthSmallest(TreeNode* root, int k) {help(root,k);return nRet;
}

三、把二叉搜索树转换为累加树

题目:给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

示例 1:

输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
示例 2:

输入:root = [0,null,1]
输出:[1,null,1]
示例 3:

输入:root = [1,0,2]
输出:[3,3,2]
示例 4:

输入:root = [3,2,4,1]
输出:[7,9,4,10]

分析:

  • 虽然BST中序遍历是升序序列,但是当前节点的父节点也比本身大,并且获取不到父节点
  • 所以我们还是根据中序遍历的性质,先遍历右子树,在遍历左子树,成为降序序列

示例代码:

TreeNode* convertBST(TreeNode* root) {help(root);return root;
}
int nSum = 0;
void help(TreeNode* root)
{if (root == nullptr){return;}help(root->right);nSum += root->val;root->val = nSum;help(root->left);
}

四、合法二叉搜索树

题目:实现一个函数,检查一棵二叉树是否为二叉搜索树。

示例 1:
输入:
    2
   / \
  1   3
输出: true
示例 2:
输入:
    5
   / \
  1   4
     / \
    3   6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
     根节点的值为 5 ,但是其右子节点值为 4

分析:

  • 根据BST左子树大于右子树性质,我们很容易写出如下代码:

boolean isValidBST(TreeNode root) {
    if (root == null) return true;
    if (root.left != null && root.val <= root.left.val)
        return false;
    if (root.right != null && root.val >= root.right.val)
        return false;
    return isValidBST(root.left)
        && isValidBST(root.right);
}

但是看如图:

符合上面的代码,缺不是一棵二叉搜索树 ,因为我们只检查了该节点的左右子节点,但是BST性质是左右子树。

  • 我们可以增加两个变量,存储最大值和最小值节点

示例代码:

bool isValidBST(TreeNode* root) {return help(root,nullptr,nullptr);
}
bool help(TreeNode* root,TreeNode* max,TreeNode* min)
{if (root == nullptr){return true;}if (max != nullptr && root->val >= max->val){return false;}if (min != nullptr && root->val <= min->val){return false;}return help(root->right,max,root) && help(root->left,root,min);
}

五、二叉搜索树中的搜索

题目:给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。

例如,

给定二叉搜索树:

4
       / \
      2   7
     / \
    1   3

和值: 2
你应该返回如下子树:

2     
     / \   
    1   3

分析:

  • 根据BST性质,如果root->val == val则返回root
  • 如果root->val > val,则遍历左子树
  • 如果root->val < val,则遍历右子树

示例代码:

TreeNode* searchBST(TreeNode* root, int val) {return help(root,val);
}
TreeNode * help(TreeNode* root, int val)
{if (root == nullptr){return nullptr;}if (root->val == val){return root;}else if (root->val > val){return help(root->left,val);}else if (root->val < val){return help(root->right,val);}return nullptr;
}

六、二叉搜索树中的插入操作

题目:给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。

示例 1:

输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]
解释:另一个满足题目要求可以通过的树是:

示例 2:

输入:root = [40,20,60,10,30,50,70], val = 25
输出:[40,20,60,10,30,50,70,null,null,25]
示例 3:

输入:root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
输出:[4,2,7,1,3,5]

分析:

示例代码:

TreeNode* insertIntoBST(TreeNode* root, int val) {return help(root,val);
}
TreeNode * help(TreeNode* root, int val)
{if (root == nullptr){root = new TreeNode(val);}if (root->val > val){root->left = help(root->left,val);}else if(root->val < val){root->right = help(root->right,val);}return root;
}

七、在 BST 中删除一个数

题目:给定一个BST和一个目标数,将该节点删除。

例如:

分析:

  • 根据BST性质,很容易找到要删除的节点A
  • 删除节点A分如下三种情况讨论
  1. A的左右节点都为空,如题示例,则:
        if (root.left == null && root.right == null)                                                                            return null;
  2. A只有一个非空子节点,那么要让这个孩子节点接替自己位置,如图:if (root.left == null) return root.right;
    if (root.right == null) return root.left;
  3. A有两个非空子节点,为了不破坏BST性质,A必须找到左子树中最大的那个节点,或者右子树最小的那个节点接替自己位置,如图:

if (root.left != null && root.right != null) {//以找右子树最小值为例
              // 找到右子树的最小节点
             TreeNode minNode = getMin(root.right);
             // 把 root 改成 minNode
             root.val = minNode.val;
             // 转而去删除 minNode
             root.right = deleteNode(root.right, minNode.val);
        }

示例代码:

TreeNode* deleteNode(TreeNode *root, int key) {if (root == nullptr){return nullptr;}if (root->val == key) {// 这两个 if 把情况 1 和 2 都正确处理了if (root->left == nullptr){return root->right;}if (root->right == nullptr){return root->left;}// 处理情况 3TreeNode* minNode = getMin(root->right);root->val = minNode->val;root->right = deleteNode(root->right, minNode->val);}else if (root->val > key){root->left = deleteNode(root->left, key);}else if (root->val < key){root->right = deleteNode(root->right, key);}return root;
}TreeNode* getMin(TreeNode* node) {// BST 最左边的就是最小的while (node->left != nullptr){node = node->left;}return node;
}

八、不同的二叉搜索树

题目:给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

示例 1:

输入:n = 3
输出:5
示例 2:

输入:n = 1
输出:1

分析:

  • 根节点可以有n种选择
  • 比如n = 5,选择3为根节点,则{1,2}就是左子树组合,{4,5}就是右子树组合
  • 左右子树组合乘积就是以3为根节点的BST种数

示例代码:

//备忘录消除一下重复子项
int numTrees(int n) {vector<vector<int>> memo(n + 1, vector<int>(n + 1,0));return help(1,n,memo);
}
int help(int nLow, int nHeight,vector<vector<int>> &memo)
{if (nLow > nHeight){return 1;}if (memo[nLow][nHeight] != 0){return memo[nLow][nHeight];}int ret = 0;for (int i = nLow; i <= nHeight; i++){//以i为根节点int nLeft = help(nLow, i - 1,memo);int nRight = help(i + 1, nHeight,memo);ret += nLeft * nRight;}memo[nLow][nHeight] = ret;return ret;
}

九、不同的二叉搜索树 II

题目:给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。

示例 1:

输入:n = 3
输出:[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]
示例 2:

输入:n = 1
输出:[[1]]

分析:

  • 根据例题8的解析,可知道BST总数
  • 只是需要保存一下每个节点信息

示例代码:

vector<TreeNode*> generateTrees(int n) {return help(1,n);
}
vector<TreeNode *> help(int nLow, int nHeight)
{vector<TreeNode *> ret;if (nLow > nHeight){ret.push_back(nullptr);return ret;}for (int i = nLow; i <= nHeight; i++){vector<TreeNode *> left = help(nLow, i - 1);vector<TreeNode *> right = help(i + 1, nHeight);for (auto & leftNode : left){for (auto &rightNode : right){TreeNode *root = new TreeNode(i);root->left = leftNode;root->right = rightNode;ret.push_back(root);}}}return ret;
}

二叉搜索树(BST)合集相关推荐

  1. 6-12 二叉搜索树的操作集

    6-12 二叉搜索树的操作集(30 分) 本题要求实现给定二叉搜索树的5种常用操作. 函数接口定义: BinTree Insert( BinTree BST, ElementType X ); Bin ...

  2. 阿里开发者招聘节 | 面试题02-04:给定一个二叉搜索树(BST),找到树中第K小的节点

    为帮助开发者们提升面试技能.有机会入职阿里,云栖社区特别制作了这个专辑--阿里巴巴资深技术专家们结合多年的工作.面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总 ...

  3. 6-1 二叉搜索树的操作集 (30 分)

    大一下半期数据结构 二叉搜索树的操作集 本题要求实现给定二叉搜索树的5种常用操作. 函数接口定义: BinTree Insert( BinTree BST, ElementType X ); BinT ...

  4. 【数据结构与算法】3.二叉搜索树(BST)、c++代码

    二叉搜索树(BST).c++代码 参考 https://blog.csdn.net/c_living/article/details/81021510

  5. 04-树7 二叉搜索树的操作集(c语言实现)

    题目 本题要求实现给定二叉搜索树的5种常用操作. 函数接口定义: BinTree Insert( BinTree BST, ElementType X ); BinTree Delete( BinTr ...

  6. 看动画学算法之:二叉搜索树BST

    文章目录 简介 BST的基本性质 BST的构建 BST的搜索 BST的插入 BST的删除 看动画学算法之:二叉搜索树BST 简介 树是类似于链表的数据结构,和链表的线性结构不同的是,树是具有层次结构的 ...

  7. 04-树7 二叉搜索树的操作集 (30 分)

    本题要求实现给定二叉搜索树的5种常用操作. 函数接口定义: BinTree Insert( BinTree BST, ElementType X ); BinTree Delete( BinTree ...

  8. 二叉搜索树 (BST)

    二叉搜索树 (BST : Binary Search Tree) 又名 二叉查找树 或 二叉排序树. 二叉搜索树: 左孩子的值 一定小于或等于 父结点的值 二叉搜索树: 右孩子的值 一定大于或等于 父 ...

  9. 算法 树7 二叉搜索树的操作集

    全部每周作业和视频思考题答案和解析 见 浙江大学 数据结构 思考题+每周练习答案汇总 题目:本题要求实现给定二叉搜索树的5种常用操作. 函数接口定义: BinTree Insert( BinTree ...

  10. 6-12 二叉搜索树的操作集 (30 分)

    本题要求实现给定二叉搜索树的5种常用操作. 函数接口定义: BinTree Insert( BinTree BST, ElementType X ); BinTree Delete( BinTree ...

最新文章

  1. 《C++面向对象高效编程(第2版)》——导读
  2. mesh和wifi中继的区别_什么是MESH WIFI?通俗易懂告诉你为什么需要它
  3. mysql优化之连接优化(open-files-limit与table_open_cache)
  4. SpringBatch 写xml文件(StaxEventItemWriter)用法(十四)
  5. Minty Fresh : So You Want To Write An Orchestration?
  6. 「JavaScript面向对象编程指南」原型
  7. android 自己定义水平和圆形progressbar 仅仅定义一些style就能够
  8. python数据结构练习
  9. MySQL与MongoDB的区别
  10. windows xp 下的putty不能使用小键盘的问题
  11. 95-138-010-源码-Function-ProcessFunction
  12. Logstash + DataHub + MaxCompute/StreamCompute 进行实时数据分析
  13. Win32下对多个的线程句柄的关闭的控制(上)
  14. TRACKER : 错误 TRK0005: 未能找到: “CL.exe”。系统找不到指定的文件。 无法打开源文件iosteam
  15. linux能安装cad快速看图不,ubuntu下能过wine安装cad快速看图
  16. 使用Java将图片转成Base64编码,并压缩至40k
  17. 英汉汉英词典,牛津高级词典,电子词典,离线英汉,汉英词典的使用方法
  18. EV充电插头相关知识学习了解
  19. TensorFlow - 正弦曲线
  20. bzoj3097: Hash Killer I

热门文章

  1. 关于网页中视频无法自动播放的问题
  2. 蓝桥杯 算法提高 质数的后代
  3. 大器晚成我服刘邦,48岁才开始创业
  4. C语言-杨辉三角的三种解法-简单易懂篇
  5. 2022-2027年中国陆地货物运输保险行业发展监测及投资战略研究报告
  6. Java现在还好找工作吗?
  7. U盘无法格式的解决办法
  8. 程序媛小姐姐甜甜恋爱过程
  9. md文件的编辑-MarkDown语法
  10. 深度强化学习-基于价值学习的高级技巧(五-1)