二叉搜索树

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用

好久不见. 提交于 2019-12-11 14:48:18
一般来说,删除节点可分为两个步骤: 首先找到需要删除的节点; 如果找到了,删除它。 说明: 要求算法时间复杂度为 O(h),h 为树的高度。 示例: root = [5,3,6,2,4,null,7] key = 3 5 / \ 3 6 / \ \ 2 4 7 给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。 一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。 5 / \ 4 6 / \ 2 7 另一个正确答案是 [5,2,6,null,4,null,7]。 5 / \ 2 6 \ \ 4 7    解: class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Solution: def deleteNode(self, root: TreeNode, key: int) -> TreeNode: if not root: return root if root.val > key: root.left = self.deleteNode(root.left, key) elif root.val < key: root.right = self.deleteNode(root.right, key)

99.恢复二叉搜索树

落爺英雄遲暮 提交于 2019-12-11 06:51:35
难度:困难 题目描述: 思路总结 :找啊找啊找规律。做过就会系列。思路就是两次中序遍历,找到两次不满足条件的节点(可能会相邻),并交换其val。 第一个节点,是第一个按照中序遍历时候前一个节点大于后一个节点,我们选取前一个节点; 第二个节点,是在第一个节点找到之后, 后面出现前一个节点大于后一个节点,我们选择后一个节点; 题解一: # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution : def recoverTree ( self , root : TreeNode ) - > None : """ Do not return anything, modify root in-place instead. """ #思路:中序遍历找到出错结点,与某结点交换。 firstNode = None secondNode = None pre = TreeNode ( float ( "-inf" ) ) stack = [ ] p = root while p or stack : while p : stack . append ( p ) p

leetcode98.验证二叉搜索树

不羁岁月 提交于 2019-12-11 04:14:46
给定一个二叉树,判断其是否是一个有效的二叉搜索树。 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数。 节点的右子树只包含大于当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。 示例 1: 输入 : 2 / \ 1 3 输出 : true 示例 2: 输入 : 5 / \ 1 4 / \ 3 6 输出 : false 解释 : 输入为 : [ 5 , 1 , 4 , null , null , 3 , 6 ] 。 根节点的值为 5 ,但是其右子节点值为 4 。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/validate-binary-search-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 完整代码 特别说明:并不是左右子树都是二叉搜索树,最终结果就是二叉搜索树 举例: [10,5,15,null,null,6,20] 左右子树的确是二叉搜索树,但是这棵树不是二叉搜索树。 那么如何改进呢? 其实二叉搜索树的中序遍历是一个递增的序列,只需稍微修改下中序遍历的递归算法就可以,只要让上一次遍历的节点的值小于当前遍历节点的值就可以,否则就不是二叉搜索树。 说明:需要特别记录下上一次遍历的节点的值是多少 这里有个坑 初始情况:int preval=INT_MIN

数据结构 树(上)

不打扰是莪最后的温柔 提交于 2019-12-08 05:02:32
数据结构 树(上) 一、概述   主要内容包含树的基本概念、二叉树(平衡二叉树、完全二叉树、满二叉树)、搜索树(二叉搜索树、平衡搜索树、AVL树、伸展树、(2,4)树、红黑树)、(a,b)树、B树等实际运用的树数据结构 二、基本知识(树的定义和属性) 1、树(非线性数据结构)运用于一些算法实现的效率会比线性数据结构(基于数组的列表和链表)快,广泛运用于文件系统目录结构、图形用户界面、MySQL数据库索引、网站、路由协议和其他计算机系统中 2、树T定义为存储一系列元素的有限节点集合,这些节点具有 parent-children 关系且满足属性:一、如果树T不为空,则它一定具有一个称为根节点 r 的特殊节点,并且该节点没有父节点;二、每个非根节点 v 都具有唯一的父节点 w ,每个具有父节点 w 的节点都是节点 w 的一个孩子 3、一个没有孩子的节点 v 称为外部节点或者叶子节点,一个有一个或多个孩子的节点 v 称为内部节点 4、树的边:一对具有父子关系的节点(u,v);树的路径:一系列节点,这些节点中任意两个连续的节点都具有父子关系 5、节点P的祖先:从根节点到该节点P所经路径上的所有节点;节点P的子孙:以该节点P为根节的子树中任意一个节点都是节点P的子孙 6、有序树:如果树中的每个节点的孩子节点都有特定的顺序,称为有序树。有序树:二叉树、霍夫曼树(信息编码)、B树

leetcode-初级-验证二叉搜索树

跟風遠走 提交于 2019-12-08 04:21:55
题意:判断一棵树是否满足二叉搜索树。 二叉搜索树的特点:左子树<根节点<右子树 解题思路:中序遍历,链栈,来实现。 对于一颗二叉树,中序遍历的结果若满足递增排序就满足二叉搜索树的条件 引用自: https://blog.csdn.net/sanmao0816/article/details/45085321 /** *解题思路:中序遍历,链栈 * Definition for binary tree * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ int flag; struct Node{//创建一个链栈节点 int val; struct Node *next; }; struct Stack{//创建一个链栈 struct Node *top;//指向链栈栈顶节点 int count;//记录链栈的节点个数 }; void InitStack(struct Stack *stack){//初始化一个空栈 stack->count = 0; stack->top = NULL; } void PushStack(struct Stack *stack,int val){//压栈 struct Node *node; node = (struct

Leetcode173. 二叉搜索树迭代器

强颜欢笑 提交于 2019-12-06 20:00:29
空间复杂度O(h)而不是O(n),因此不能直接在初始化函数中做中序遍历将结果存储到数组中。 next()和hasNext()时间复杂度为O(1) 首先本题很容易想到用二叉树的中序遍历去解决,外加注意点1.我们得到思路:仅仅将中序遍历最小值之前的节点压入栈中,当next时我们将栈顶元素取出即为最小值返回,当然在此之前需要将下一个最小值找到,并将路径上的所有节点压入栈中以供使用,查看是否迭代到头只需判断栈是否为空即可,如下: class BSTIterator { private: stack<TreeNode*>ss; public: BSTIterator(TreeNode* root) { while(root) { while (root) { ss.push(root); root=root->left; } } } /** @return the next smallest number */ int next() { TreeNode* cur=ss.top(); int num=cur->val; ss.pop(); cur=cur->right; while (cur) { ss.push(cur); cur=cur->left; } return num; } /** @return whether we have a next smallest number */

最优二叉搜索树

巧了我就是萌 提交于 2019-12-06 04:38:05
定义 设 是有序集,且 ,表示有序集 S 的二叉搜索树利用二叉树的结点来存储有序集中的元素。它具有下述性质:存储于 每个结点中的元素 x 大于其左子树中任一结点所存储的元素,小于其右子树中任一结点所存储的元素。二叉搜索树的叶节点是形如 的开区间。在表示 S 的二叉搜索树中搜索一个元素 x ,返回的结果有两种情况: ① 在二叉搜索树的内结点中找到 ,令其概率为 ② 在二叉搜索树的叶节点中确定 ,令其概率为 。 表示 x 小于 的值的概率, 表示所有 x 大于 的值的概率, 表示 x 位于 和 值的概率。 显然,有 , , , 称为集合 S 的存取概率分布。 在表示 S 的二叉搜索树 T 中,设存储元素 的结点深度为 ,叶节点 的结点深度为 ,则 表示在二叉搜索树 T 中进行一次搜索所需的平均比较次数,p又称为二叉搜索树 T 的平均路长。在一般情况下,不同的二叉搜索树的平均路上是不相同的。 所以,最优二叉搜索树问题是对于有序集 S 及其存取概率分布 ,在所有表示有序集 S 的二叉搜索树中找出一颗具有最小平均路长的二叉搜索树。 最优子结构性质 二叉搜索树 T 的一棵含有结点 和叶节点 的子树可以看做是有序集 关于全集合 的一棵二叉搜索树,其存取概率为下面的条件概率 设 是有序集 关于存取概率 的一棵最优二叉搜索树,其平均路长为 。 的根结点存储元素 。其左右子树 和 的平均路长分别为 和

leetcode 98. 验证二叉搜索树 java

安稳与你 提交于 2019-12-05 22:27:10
题目: 给定一个二叉树,判断其是否是一个有效的二叉搜索树。 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数。 节点的右子树只包含大于当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。 解题: class Solution { public boolean helper(TreeNode node, Integer lower, Integer upper) { if (node == null) return true; int val = node.val; if (lower != null && val <= lower) return false; if (upper != null && val >= upper) return false; if (! helper(node.right, val, upper)) return false; if (! helper(node.left, lower, val)) return false; return true; } public boolean isValidBST(TreeNode root) { return helper(root, null, null); } } 来源: https://www.cnblogs.com/yanhowever/p/11947583.html

98. 验证二叉搜索树(深搜)

两盒软妹~` 提交于 2019-12-05 20:39:42
   观察可以发现,只要进行一遍中序遍历就可以解决,主要的难点是要保存上一个节点的值与下一个节点进行比较,这可以设置一个全局变量,把它作为前一节点值,每次中序都可以让当前节点值和它进行比较,如果违反顺序规则,则直接return退出,这里又可以设置一个flag来帮助我们剪枝。   LeetCode测试用例有一个是int类型的最小值 [-2147483648] ,这让我的初始节点值设置的不够小,查了一下资料可以用long long类型的LONG_MIN 1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 11 //保存前一个节点的值 12 class Solution { 13 public: 14 long long pre=LONG_MIN; //卡边界(真的恶心) 15 bool flag=true; 16 bool isValidBST(TreeNode* root) { 17 if(!root||!flag) return 1; //剪枝 18

DS AVL树详解

浪子不回头ぞ 提交于 2019-12-05 19:29:12
    先说说二叉搜索树: 是有序的二叉树,根值>左节点值,右节点值>根值。     如果要查找某个值,二叉搜索树和二分查找一样,每进行一次值比较,就会减少一半的遍历区间。     但是,如果树插入的值一直递增/递减,就会出现这种情况:     这样,二叉树性能就完全失去了,直接退化成了顺序表,查找效率低下。     由此,引入了能保持性能最佳的二叉搜索树。      AVL树: 具有 高度平衡 的二叉搜索树 。     性质: 1.它的左右子树都是AVL树        2. 左右子树高度差(简称平衡因子)的绝对值不超过1       搜索的时间复杂度: O(log2(n))        AVL树节点      struct AVLTree{ pair<K,V> kv; AVLTreeNode* left; AVLTreeNode* right; AVLTreeNode* parent; int bf; //balance factor };    与二叉搜索树不同的是引入了父节点(方便后面讲的旋转)和平衡因子(保持高度平衡的核心)。        AVL树的插入:       在插入节点后,需要调整平衡:       1.bf更新规则:新增在左 父亲bf-1 ; 新增在右 父亲bf+1        2.持续往祖先更新 如果 祖先bf==0,祖先肯定是从1或者-1变来的