代码随想录算法训练营第二十一天,二十二,二十三| 530. 二叉搜索树的最小绝对差 501. 二叉搜索树中的众数 236. 二叉树的最近公共祖先 235. 二叉搜索树的最近公共祖先 701. 二叉搜索树中的插入操作 450. 删除二叉搜索树中的节点
530. 二叉搜索树的最小绝对差
https://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/
TreeNode pre = null;
int res = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
if (root == null) return 0;
preorder(root);
return res;
}
public void preorder(TreeNode node){
if (node == null) return;
preorder(node.left);
if (pre != null){
res = Math.min(res,node.val - pre.val);
}
pre = node;
preorder(node.right);
}
总结:二叉搜索树的中序就是从小到大排序,每次中序的过程中记录下来上一个节点,每次计算当前值和上一个值的差,注:处理完自己的逻辑再令pre=自己,就是给下一个节点指定了pre
501. 二叉搜索树中的众数
https://leetcode.cn/problems/find-mode-in-binary-search-tree/description/
TreeNode pre = null;
int maxcount = 0;
int curcount = 0;
List<Integer> res = new ArrayList<>();
public int[] findMode(TreeNode root) {
preorder(root);
int[] res1 = new int[res.size()];
for (int i = 0; i < res.size(); i++) {
res1[i] = res.get(i);
}
return res1;
}
public void preorder(TreeNode node){
if (node == null) return;
preorder(node.left);
if (pre == null || pre.val != node.val){
curcount = 1;
}else {
curcount++;
}
if (curcount > maxcount){
res.clear();
res.add(node.val);
maxcount = curcount;
}else if (curcount == maxcount){
res.add(node.val);
}
pre = node;
preorder(node.right);
}
总结:由于是二叉搜索树,中序遍历是有序的,所以相同的节点分类,如果是第一个i点就置curcount为1,不是第一个就直接++,加完了之后看curcount如果等于maxcount了就直接进res,如果大于了就清空res再进res。 这个方法要保存pre为前置节点。
236. 二叉树的最近公共祖先
https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/description/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q){
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(left == null && right == null) { // 若未找到节点 p 或 q
return null;
}else if(left == null && right != null) { // 若找到一个节点
return right;
}else if(left != null && right == null) { // 若找到一个节点
return left;
}else { // 若找到两个节点
return root;
}
}
总结:首先一定是后序,每次从根去看左右子树,返回的节点是左右子树中找到的是p还是q还是什么都没有,再对这三者进行判断,找到了最小公共祖先之后就返回这个点,一直返回这个点没否则就返回单左或单右。 由于题中默认一定有祖先,所以如果发生q是p的孩子的情况,直接遍历到p的时候返回p就好,不用管p下面还有没有q,因为最后如果q在p下面,返回p没毛病,如果q不在p下面,返回p更没毛病。
235. 二叉搜索树的最近公共祖先
https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/description/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root.val > p.val && root.val > q.val){
return lowestCommonAncestor(root.left,p,q);
}
if (root.val < p.val && root.val < q.val){
return lowestCommonAncestor(root.right,p,q);
}
return root;
}
总结:还是题中默认p,q一定有祖先,所以当遍历到一个点 p,q在不同的子树中时,这个点就是最小祖先。
701. 二叉搜索树中的插入操作
https://leetcode.cn/problems/insert-into-a-binary-search-tree/description/
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) return new TreeNode(val);
insertHelper(root,val);
return root;
}
public void insertHelper(TreeNode node,int val){
if (val < node.val){
if (node.left != null){
insertHelper(node.left,val);
}else {
node.left = new TreeNode(val);
}
}else {
if (node.right != null){
insertHelper(node.right,val);
}else {
node.right = new TreeNode(val);
}
}
}
总结:我没有考虑转换树形结构的问题,我只是找到位置然后插入,前序遍历,看当前节点如果 val应该在node左边且node的left还为null,就插进去,这种遍历。
450. 删除二叉搜索树中的节点
https://leetcode.cn/problems/delete-node-in-a-bst/description/
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return null;
if (root.val == key){
if (root.left == null){
return root.right;
}else if (root.right == null){
return root.left;
}else {
TreeNode cur = root.right;
while (cur.left != null){
cur = cur.left;
}
cur.left = root.left;
root = root.right;
return root;
}
}
if (root.val > key) root.left = deleteNode(root.left,key);
if (root.val < key) root.right = deleteNode(root.right,key);
return root;
}
总结:二叉搜索树的删除在于 如果删除的点没有左右孩子,直接返回null,有左没右,返回左,有右没左,返回右,左右都有,把要删的点的左子树的根放到右子树的最左节点的左边(题目关键在这)
669. 修剪二叉搜索树
https://leetcode.cn/problems/trim-a-binary-search-tree/description/
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null) return null;
if (root.val < low){
return trimBST(root.right,low,high);
}
if (root.val > high){
return trimBST(root.left,low,high);
}
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
return root;
}
总结:前序遍历,如果节点值比low还小,就返回右子树替代自己,如果节点值比high还大,就返回左子树替代自己。
108. 将有序数组转换为二叉搜索树
https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/description/
public TreeNode sortedArrayToBST(int[] nums) {
if (nums.length == 0) return null;
TreeNode node = helper(nums, 0, nums.length - 1);
return node;
}
public TreeNode helper(int[] nums,int low,int high){
if (low > high ) return null;
int mid = low + (high - low) / 2;
TreeNode node = new TreeNode(nums[mid]);
node.left = helper(nums,low,mid - 1);
node.right = helper(nums,mid + 1,high);
return node;
}
总结:有序数组构造平衡二叉树,每次二分查找就好,自然就是平衡的。
538. 把二叉搜索树转换为累加树
https://leetcode.cn/problems/convert-bst-to-greater-tree/description/
TreeNode pre = null;
public TreeNode convertBST(TreeNode root) {
if (root == null) return null;
helper(root);
return root;
}
public void helper(TreeNode node){
if (node == null) return;
helper(node.right);
if (pre == null){
node.val = node.val;
}else {
node.val += pre.val;
}
pre = node;
helper(node.left);
}
总结:遍历顺序:右根左,用pre记录上一个节点,每个节点的新值都是自己的旧值+pre的值。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?