东哥带你刷二叉搜索树(基操篇) :: labuladong的算法小抄 #1081
Replies: 39 comments 11 replies
-
这里我觉得其实问题的不大, 如果是个复杂的数据结构,这里里修改 |
Beta Was this translation helpful? Give feedback.
-
@biaoboss 不是,如果不只有 val 字段呢?如果有的语言可能存的是值而不是指针呢?实际情况是你根本不知道 TreeNode 的里面的数据是什么样子,所以最好的办法就是不要动数据域,只单纯地操作数据结构,即只去操作 |
Beta Was this translation helpful? Give feedback.
-
温馨提示:删除二叉树节点的思路过不了450.删除二叉搜索树中的节点(中等)这一题 |
Beta Was this translation helpful? Give feedback.
-
有个疑问:"情况 3:A 有两个子节点,麻烦了,为了不破坏 BST 的性质,A 必须找到左子树中最大的那个节点,或者右子树中最小的那个节点来接替自己。" 按照性质,应该只能找到右子树最小节点来替代呀,为什么找左子树最大也成立呢 |
Beta Was this translation helpful? Give feedback.
-
判断isValidBST, 也可以利用BST的inorder traversal 所有元素应该是递增的属性. class Solution:
def __init__(self):
self.prev = float('-inf')
self.bool = True
def isValidBST(self, root: Optional[TreeNode]) -> bool:
self.inorder(root)
return self.bool
def inorder(self, node):
if node is None:
return
self.inorder(node.left)
if self.prev == float('-inf'):
self.prev = node.val
else:
if node.val <= self.prev:
self.bool=False
else:
self.prev = node.val
self.inorder(node.right) |
Beta Was this translation helpful? Give feedback.
-
@ryanmingxinzhang 右子树最小和左子树最大不是对称的概念吗,既然右小可以接替原来的root,那左大必然可以,不存在谁更高贵 |
Beta Was this translation helpful? Give feedback.
-
root.right = deleteNode(root.right, minNode.val); 为什么第一行和第二行交换一下顺序,答案就不对的啊,左子树应该不受影响啊 |
Beta Was this translation helpful? Give feedback.
-
BST 代码框架,学到了学到了!! |
Beta Was this translation helpful? Give feedback.
-
deleteNode�d存在内存泄漏吗? |
Beta Was this translation helpful? Give feedback.
-
js 98. 验证二叉搜索树 var isValidBST = function (root) {
return check(root);
/* 限定以 node 为根的子树节点必须满足 max > node.val > min */
function check(node, min = -Infinity, max = Infinity) {
// base case
if (node === null) return true;
// 若 root.val 不符合 max 和 min 的限制,说明不是合法 BST
if (node.val <= min || node.val >= max) {
return false;
}
// 限定左子树的最大值是 node.val,右子树的最小值是 node.val
return (
check(node.left, min, node.val) &&
check(node.right, node.val, max)
);
}
}; js 700. 二叉搜索树中的搜索 var searchBST = function(root, val) {
if (root === null) return null;
// 去左子树搜索
if (val < root.val) return searchBST(root.left, val);
// 去右子树搜索
if (val > root.val) return searchBST(root.right, val);
// 找到
return root;
}; js 701. 二叉搜索树中的插入操作 var insertIntoBST = function (root, val) {
// 找到空位置插入新节点
if (root === null) return new TreeNode(val);
// if (val === root.val)
// BST 中一般不会插入已存在元素
if (val < root.val) {
root.left = insertIntoBST(root.left, val);
}
if (val > root.val) {
root.right = insertIntoBST(root.right, val);
}
return root;
}; js 450. 删除二叉搜索树中的节点 var deleteNode = function (root, key) {
if (root === null) return null;
if (root.val === key) {
// 找到啦,进行删除
// 恰好是末端节点,直接删除
if (root.left === null && root.right === null) {
return null;
}
// 只有一个非空子节点,那么它要让这个孩子接替自己的位置
if (root.left !== null && root.right === null) return root.left;
if (root.left === null && root.right !== null) return root.right;
// 有两个非空子节点
// 找到右子树的最小节点
const rightMinNode = getMin(root.right);
// 删除右子树最小的节点
root.right = deleteNode(root.right, rightMinNode.val);
// 把 root 改成 minNode
rightMinNode.left = root.left;
rightMinNode.right = root.right;
root = rightMinNode;
} else if (key < root.val) {
// 去左子树找
root.left = deleteNode(root.left, key);
} else if (key > root.val) {
// 去右子树找
root.right = deleteNode(root.right, key);
}
return root;
function getMin(node) {
while (node.left) {
node = node.left;
}
return node;
}
}; |
Beta Was this translation helpful? Give feedback.
-
一颗完整的 js 二叉搜索树实现: class TreeNode {
constructor(val) {
this.val = val;
this.count = 1;
this.left = null;
this.right = null;
}
}
class BinarySearchTree {
constructor() {
this.root = null;
}
insert(val, node = this.root) {
// 处理空树
if (this.root === null) {
this.root = new TreeNode(val);
return this.root;
}
// 找到空位置插入新节点
if (node === null) return new TreeNode(val);
// 找到,计数加 1
if (val === node.val) node.count++;
// 去左子树搜索
if (val < node.val) node.left = this.insert(val, node.left);
// 去右子树搜索
if (val > node.val) node.right = this.insert(val, node.right);
return node;
}
find(val, node = this.root) {
if (node === null) return null;
// 去左子树搜索
if (val < node.val) return this.find(val, node.left);
// 去右子树搜索
if (val > node.val) return this.find(val, node.right);
// 找到
return node;
}
remove(val, node = this.root) {
// 没找到
if (node === null) return null;
if (node.val === val) {
// 找到啦,进行删除
// 恰好是末端节点,直接删除
if (node.left === null && node.right === null) {
return null;
}
// 只有一个非空子节点,那么它要让这个孩子接替自己的位置
if (node.left !== null && node.right === null) return node.left;
if (node.left === null && node.right !== null) return node.right;
// 有两个非空子节点
// 找到右子树的最小节点
const rightMinNode = this.getMinNode(node.right);
// 删除右子树最小的节点
node.right = this.remove(rightMinNode.val, node.right);
// 把 root 改成 minNode
rightMinNode.left = node.left;
rightMinNode.right = node.right;
node = rightMinNode;
} else if (val < node.val) {
// 去左子树找
node.left = this.remove(val, node.left);
} else if (val > node.val) {
// 去右子树找
node.right = this.remove(val, node.right);
}
return node;
}
getMinNode(node = this.root) {
while (node.left) {
node = node.left;
}
return node;
}
getMaxNode(node = this.root) {
while (node.right) {
node = node.right;
}
return node;
}
bfs() {
if (this.root === null) return [];
const list = [];
const q = [this.root];
while (q.length) {
const sz = q.length;
for (let i = 0; i < sz; i++) {
const node = q.shift();
list.push(node.val);
if (node.left) q.push(node.left);
if (node.right) q.push(node.right);
}
}
return list;
}
dfsPreOrder(node = this.root, list = []) {
if (this.root === null) return [];
list.push(node.val);
if (node.left) this.dfsPreOrder(node.left, list);
if (node.right) this.dfsPreOrder(node.right, list);
return list;
}
dfsInOrder(node = this.root, list = []) {
if (this.root === null) return [];
if (node.left) this.dfsInOrder(node.left, list);
list.push(node.val);
if (node.right) this.dfsInOrder(node.right, list);
return list;
}
dfsPostOrder(node = this.root, list = []) {
if (this.root === null) return [];
if (node.left) this.dfsPostOrder(node.left, list);
if (node.right) this.dfsPostOrder(node.right, list);
list.push(node.val);
return list;
}
}
const tree = new BinarySearchTree();
tree.insert(9);
tree.insert(9);
tree.insert(4);
tree.insert(6);
tree.insert(20);
tree.insert(170);
tree.insert(15);
tree.insert(1);
console.log(tree.bfs());
console.log(tree.dfsPreOrder());
console.log(tree.dfsInOrder());
console.log(tree.dfsPostOrder());
console.log(tree.find(15));
console.log(tree.remove(15));
console.log(tree.find(15)); |
Beta Was this translation helpful? Give feedback.
-
@Zoran-Kwok minNode是右子树的一个节点,第二行和第一行交换位置,意味着你修改了右子树,再去执行deleteNode |
Beta Was this translation helpful? Give feedback.
-
//关注当前节点与左右孩子的行为
//当前结点root的左孩子root.left
max = root.val;
min = min;//最小值保持不变
//当前结点root的右孩子root.right
min = root.val,
max = max;//最大值保持不变
//左右孩子分别将root的min, max约束传递下来
//min只有从根一直向左传递才会为null
//max只有从根一直向右传递才会为null
//中途只要变过方向约束条件都会变 |
Beta Was this translation helpful? Give feedback.
-
我发现不对劲的地方,450 题,删除二叉搜索树的节点里面 |
Beta Was this translation helpful? Give feedback.
-
@ErronZrz 多思考是好的,但需要用实践来检验想法,不妨把你实现的代码贴出来 |
Beta Was this translation helpful? Give feedback.
-
@Maxiah 方法确实有很多种,但你说的这个方案不好,因为你这样会显著提高 BST 的高度,实际应用会大幅降低 BST 的搜索效率。 |
Beta Was this translation helpful? Give feedback.
-
很经典,就是没那么直观,要想一会才能看懂,比如第一题我是这么理解的:min的值是当前root的取值下限,max的值其实就是当前root的取值上限,超出这个范围就达到了递归出口,传参null,意思其实就是(-∞,+∞) |
Beta Was this translation helpful? Give feedback.
-
请问博主有没有BST插入多个数讲解,从而维护BST的性质? |
Beta Was this translation helpful? Give feedback.
-
func deleteNode(root *TreeNode, key int) *TreeNode {
if root == nil {
return nil
}
if key < root.Val {
root.Left = deleteNode(root.Left, key)
return root
} else if key > root.Val {
root.Right = deleteNode(root.Right, key)
return root
}
//与本节点相同的情况
if root.Left == nil && root.Right == nil {
return nil
} else if root.Left == nil && root.Right != nil {
return root.Right
} else if root.Left != nil && root.Right == nil {
return root.Left
}
root.Val, root.Right = FoundMin(root.Right)
return root
}
func FoundMin(root *TreeNode) (int, *TreeNode) { //返回树的最小值,并删除最小值节点
if root.Left == nil {
return root.Val, root.Right
}
var temp int
temp, root.Left = FoundMin(root.Left)
return temp, root
} |
Beta Was this translation helpful? Give feedback.
-
----------check in |
Beta Was this translation helpful? Give feedback.
-
java : 450 删除二叉树结点 可通过 public TreeNode deleteNode(TreeNode root, int key) {
if ( root == null ) { return null; }
if ( root.val == key ) {
return insertNode(root.right,root.left);
}
else if ( root.val > key ) {
root.left = deleteNode(root.left,key);
}
else {
root.right = deleteNode(root.right,key);
}
return root;
}
TreeNode insertNode(TreeNode root, TreeNode tree){
if ( root == null ) { return tree; }
root.left = insertNode(root.left,tree);
return root;
} |
Beta Was this translation helpful? Give feedback.
-
打卡 |
Beta Was this translation helpful? Give feedback.
-
东哥你的总结太完美了,比huifeng guan的要好! |
Beta Was this translation helpful? Give feedback.
-
验证二叉搜索树可以利用BST的中序遍历特性: class Solution {
// 记录中序遍历的前驱
TreeNode pre;
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
// 判断左子树
if (!isValidBST(root.left)) {
return false;
}
// 判断中序遍历的结果是否合法
if (pre != null && pre.val >= root.val) return false;
// 更新中序遍历的前驱
pre = root;
// 判断右子树
return isValidBST(root.right);
}
} |
Beta Was this translation helpful? Give feedback.
-
提个疑问,希望有人解答一下: 在进行操作root = minNode; 的时候,为啥不用将root的做右指针断开 |
Beta Was this translation helpful? Give feedback.
-
python3实现,把return的地方改的更统一且傻瓜了一些hhhh
|
Beta Was this translation helpful? Give feedback.
-
看到一种关于 class Solution {
long pre = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
// 访问左子树
if (!isValidBST(root.left)) {
return false;
}
// 访问当前节点:如果当前节点小于等于中序遍历的前一个节点,说明不满足BST,返回 false;否则继续遍历。
if (root.val <= pre) {
return false;
}
pre = root.val;
// 访问右子树
return isValidBST(root.right);
}
}
作者:Sweetiee 🍬
链接:https://leetcode.cn/problems/validate-binary-search-tree/solutions/232885/zhong-xu-bian-li-qing-song-na-xia-bi-xu-miao-dong-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 |
Beta Was this translation helpful? Give feedback.
-
有一点不是很明白,在递归的时候,如果只是查询则直接return BST(root.left, target);,如果涉及改则需要接收返回值root.left = BST(root.left, target);,请问这是为什么呢? |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
700.二叉搜索树中的搜索我的思考如果使用递归遍历二叉树的思路,其实递归总是会返回给上层的。 这题我的思路,分为两种情况 代码使用GO语言解答 /**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func searchBST(root *TreeNode, val int) *TreeNode {
node := root
for node != nil && node.Val != val { //跳出循环的条件,节点为空>整棵树都没有符合条件的 或者 节点的值等于搜索的值>这个节点就是答案
if node.Val > val {
node = node.Left
} else { //node.Val < val
node = node.Right
}
}
return node
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
文章链接点这里:东哥带你刷二叉搜索树(基操篇)
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions