List list;
return list.stream().mapToInt(Integer::intValue).toArray();
题目链接/文章讲解:代码随想录
题目链接:https://leetcode.cn/problems/minimum-absolute-difference-in-bst/
给你一个二叉搜索树的根节点 root
,返回 树中任意两不同节点值之间的最小差值 。
把二叉搜索树树转成中序数组,比较两个数字之间的差即可。在数组上就可以以全局角度进行查看。
class Solution {
public List list = new ArrayList<>();
public int getMinimumDifference(TreeNode root) {
traverse(root);
int[] arr = list.stream().mapToInt(Integer::intValue).toArray();
int res = Integer.MAX_VALUE;
for (int i=1; i
题目链接/文章讲解:代码随想录
题目链接:https://leetcode.cn/problems/find-mode-in-binary-search-tree/
给你一个含重复值的二叉搜索树(BST)的根节点 root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
二叉搜索树转中序数组,使用变量记录当前数字以及遇到的次数,使用一个List记录所有的结果,如果记录更新了,就刷新List。
class Solution {
public int[] findMode(TreeNode root) {
List list = new ArrayList<>();
traverse(root, list);
int count = 0;
int maxCount = 0;
int pre = Integer.MAX_VALUE;
List result = new ArrayList<>();
for (int i=0; i maxCount) {
result.clear();
maxCount = count;
result.add(num);
}
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
public void traverse(TreeNode node,List list) {
if (node == null) return;
traverse(node.left, list);
list.add(node.val);
traverse(node.right, list);
}
}
题目链接/文章讲解:代码随想录
题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/description/
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)
如果某个节点是两个节点p,q的公共祖先,那么q,p一定在node节点的左右子树当中。搜索该树的左右节点,观察两个子树当中是否出现过这两个节点。
class Solution {
public TreeNode result;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return traverse(root, p, q);
}
// 1. 递归参数和返回值
// 参数: p节点,q节点,当前节点
// 返回值:返回最近的公共节点
public TreeNode traverse(TreeNode node, TreeNode p, TreeNode q) {
// 2. 终止条件
// 遇到空节点,或者找到了p,q
if (node == null || node == p || node == q) {return node;}
// 3. 单层递归逻辑
// 后序遍历
TreeNode left = traverse(node.left, p, q);
TreeNode right = traverse(node.right, p, q);
// 检查左右树的返回结果
// 如果左树右树都有找到了,说明当前节点就是公共祖先
if (left != null && right != null) {return node;}
// 左数找到了结果,右树没有,说明公共节点在左树里
if (left != null) {return left;}
// 左数没找到,右数找到了,说明公共节点在右数
return right;
// 第二种递归逻辑
// 左树没有,就只能看右树的结果了
if (left == null) return right;
// 左树有,但是右树没有,就只能看左树的结果了
if (right == null) return left;
// 左树右树都有,说明当前节点是公共节点
return node;
}
}
题目链接/文章讲解:代码随想录
题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/
二叉搜索树和普通二叉树区别在于有序,通过比较顺序可以确定左右分支要搜索哪一个。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return traverse(root, p, q);
}
public TreeNode traverse(TreeNode node, TreeNode p, TreeNode q) {
if (node == null) {return node;}
if (node.val > p.val && node.val > q.val) { // 说明公共节点在左树
return traverse(node.left, p, q);
}
if (node.val < p.val && node.val < q.val) { // 说明公共节点在右树
return traverse(node.right, p, q);
}
// 不在左树,也不在右树,就是当前节点
return node;
}
}
题目链接/文章讲解:代码随想录
题目链接:https://leetcode.cn/problems/insert-into-a-binary-search-tree/
给定二叉搜索树(BST)的根节点 root
和要插入树中的值 value
,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
插入到底层null节点,就搜索到一个合适的位置插入就行。不需要改变原来的树的结构。
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
return traverse(root, val);
}
// 参数:当前节点,需要插入的值
// 返回值: 返回插入之后的当前节点
public TreeNode traverse(TreeNode node, int val) {
// 终止条件
if (node == null) {return new TreeNode(val);}
// 向左树插入
if (node.val > val) {node.left = traverse(node.left, val);}
// 向右树插入
if (node.val < val) {node.right = traverse(node.right, val);}
return node;
}
}
题目链接/文章讲解:代码随想录
题目链接:https://leetcode.cn/problems/delete-node-in-a-bst/description/
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
找到需要删除的节点,删除该节点,重新构建该节点。
class Solution1 {
public TreeNode deleteNode(TreeNode root, int key) {
return tracaback(root, key);
}
public TreeNode tracaback(TreeNode node, int key) {
if (node == null) return null;
// 交给对应的子树进行删除操作,获取删除后的子树
if (node.val < key) node.right = tracaback(node.right, key);
if (node.val > key) node.left = tracaback(node.left, key);
// 重构当前节点
if (node.val == key) {
// 叶子节点替换成null节点(可以省略)
// if (node.left == null && node.right == null) return null;
// 右树挂载到左树最右
if (node.left != null) {
TreeNode temp = node.left;
while (temp.right != null) temp = temp.right;
temp.right = node.right;
return node.left;
}
return node.right;
// // 左树迁移到右树最左
// if (node.right != null) {
// TreeNode temp = node.right;
// while (temp.left != null) {
// temp = temp.left;
// }
// temp.left = node.left;
// return node.right;
// }
// return node.left;
}
// 返回重构后的当前节点
return node;
}
}
题目链接/文章讲解:代码随想录
题目链接:https://leetcode.cn/problems/trim-a-binary-search-tree/description/
给你二叉搜索树的根节点 root
,同时给定最小边界low
和最大边界 high
。通过修剪二叉搜索树,使得所有节点的值在[low, high]
中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。
二叉搜索树,有序,修剪子树,再检查当前节点是否在边界之内,返回修剪之后的节点;
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
return traverse(root, low, high);
}
// 参数:当前节点,值的范围
// 返回值:修建后的当前节点
public TreeNode traverse(TreeNode node, int low, int high) {
// 终止条件: 遇到空节点,没有修剪操作再需要了
if (node == null) {return node;}
// 单层递归逻辑:修建左右子树,修剪自己
// 后序遍历:因为右树是可以大于当前节点本身的
node.left = traverse(node.left, low, high);
node.right = traverse(node.right, low, high);
if (node.val < low) {return node.right;}
if (node.val > high) {return node.left;}
return node;
}
}
题目链接/文章讲解:代码随想录
题目链接:. - 力扣(LeetCode)
有序数组,转二叉平衡搜索树。按照二分查找顺序构架节点,选中间值作为节点,切割左右数组,构成子节点。
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return traverse(nums, 0, nums.length);
}
// 参数:有序数组,有序数组的区间(左闭右开)
// 返回值:组装好的节点
public TreeNode traverse(int[] nums, int low, int high) {
// 终止条件: 空数组,null节点
if (low == high) {return null;}
// 单层递归逻辑:
int middle = (low + high) / 2;
TreeNode node = new TreeNode(nums[middle]);
node.left = traverse(nums, low, middle);
node.right = traverse(nums, middle+1, high);
return node;
}
}
题目链接/文章讲解:代码随想录
题目链接:https://leetcode.cn/problems/convert-bst-to-greater-tree/description/
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node
的新值等于原树中大于或等于 node.val
的值之和。
右 中 左,遍历顺序。从右子树收集和,加到当前节点,再把收集到的和送给左子树。
递归函数,参数,返回值:当前节点收集的所有和;当前节点,之前累积的和;返回收集的和。
终止条件:遇到空节点,表示该分支收集过程结束,返回收集的和
单层逻辑:先收集右子树的和,合并到当前节点,再把当前收集的和传递给左子树,最终返回收集的所有的和。
方法2:可以使用一个sum变量,记录当前收集的和,单纯的反中序遍历即可。
class Solution {
public TreeNode convertBST(TreeNode root) {
traverse(root, 0);
return root;
}
public int traverse(TreeNode node, int addon) {
// 空节点,返回当前积累的值
if (node == null) return addon;
// 收集右子树积累的值
int right = traverse(node.right, addon);
// 收集右子树的积累值,合并到当前节点中
node.val = node.val + right;
// 把当前节点收集的值,传递到左子树中
int left = traverse(node.left, node.val);
// 把左节点收集的整个子树的值,返回给父节点
return left;
}
}
// 方法2
class Solution {
int sum;
public TreeNode convertBST(TreeNode root) {
sum = 0;
traverse(root);
return root;
}
// 按右中左顺序遍历,累加即可
public void traverse(TreeNode root) {
if (root == null) return;
// 收集右子树的和
traverse(root.right);
// 叠加当前收集的和
sum += root.val;
root.val = sum;
// 收集左子树的和
traverse(root.left);
}
}