LeetCode 235. 二叉搜索树的最近公共祖先

分析1.0 

二叉搜索树根节点元素值大小介于子树之间,所以只要找到第一个介于他俩之间的节点就行

  1. class Solution {
  2. public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
  3. if(root.val >= p.val && root.val <= q.val){
  4. return root;
  5. }else if(root.val >= q.val && root.val <= p.val){
  6. return root;
  7. }
  8. else if(root.val >= p.val && root.val >= q.val){
  9. return lowestCommonAncestor(root.left, p, q);
  10. }else{
  11. return lowestCommonAncestor(root.right, p, q);
  12. }
  13. }
  14. }

LeetCode 701.二叉搜索树中的插入操作

分析1.0

搜索树插入的新节点替代了原本的空分叉

find 空分叉 插入

  1. class Solution {
  2. public TreeNode insertIntoBST(TreeNode root, int val) {
  3. if(root == null){
  4. return new TreeNode(val);
  5. }
  6. if(val > root.val){
  7. if(root.right == null){
  8. root.right = new TreeNode(val);
  9. }else {
  10. insertIntoBST(root.right, val);
  11. }
  12. }else{
  13. if(root.left == null){
  14. root.left = new TreeNode(val);
  15. }else {
  16. insertIntoBST(root.left, val);
  17. }
  18. }
  19. return root;
  20. }
  21. }

ps. 这里先确定是左边,再看是否为空的思路挺好

LeetCode 450.删除二叉搜索树中的节点

分析1.0

删除节点,找到节点分情况讨论

  1. 节点是叶子节点,直接删除
  2. 节点是分支节点,找左子树的最大值或右子树的最小值节点的pre节点,左树最大值节点可能有左子树,右树最小值节点可能有右子树,pre节点还可能是当前节点
    1. 有左子树有右子树 
    2. 有左子树无右子树
    3. 无左子树有右子树
  3. 删除节点要知道这个节点的父节点 每次递归前先令pre = 当前节点
  4. 还要清楚待删节点是父节点的左节点还是右节点,设置参数flag指示
  1. class Solution {
  2. public TreeNode deleteNode(TreeNode root, int key) {
  3. if(root == null){
  4. return null;
  5. }
  6. TreeNode pre = new TreeNode(-1);
  7. pre.left = root;
  8. pre.right = root;
  9. return delete(root, key, pre, 0);
  10. }
  11. public TreeNode delete(TreeNode root, int key, TreeNode pre, int flag){
  12. if(root == null){
  13. return null;
  14. }
  15. if(key > root.val){
  16. flag = 1;
  17. pre = root;
  18. delete(root.right, key, pre, flag);
  19. }else if(key < root.val){
  20. flag = -1;
  21. pre = root;
  22. delete(root.left, key, pre, flag);
  23. }else {
  24. // 是叶节点
  25. if(root.left == null && root.right == null){
  26. if(pre.val == -1){
  27. return null;
  28. }
  29. if(flag == -1){
  30. pre.left = null;
  31. }else{
  32. pre.right = null;
  33. }
  34. }
  35. // 分支节点 有左子树没右子树 有左子树有右子树 找左子树最大节点的父节点
  36. else if(root.left != null){
  37. TreeNode target = findLeftTree(root.left, root);
  38. // 如果target是左子树树根-左子树无右子树
  39. int swap = 0;
  40. if(target.val == root.val){
  41. swap = target.left.val;
  42. target.left = root.left.left;
  43. }else{
  44. swap = target.right.val;
  45. // 可能最大节点target.right有左子树
  46. target.right = target.right.left;
  47. }
  48. //System.out.println("pre节点为"+pre.val);
  49. if(flag == -1){
  50. pre.left.val = swap;
  51. }else{
  52. pre.right.val = swap;
  53. }
  54. }
  55. // 分支节点 有右子树没左子树
  56. else if(root.right != null && root.left == null){
  57. TreeNode target = findRightTree(root.right, root);
  58. int swap = 0;
  59. if(target.val == root.val){
  60. swap = target.right.val;
  61. target.right = target.right.right;
  62. }else{
  63. swap = target.left.val;
  64. target.left = target.left.right;
  65. }
  66. //System.out.println("target节点为"+pre.val);
  67. if(flag == -1){
  68. pre.left.val = swap;
  69. }else{
  70. pre.right.val = swap;
  71. }
  72. }
  73. // 分支节点
  74. }
  75. return root;
  76. }
  77. // pre为待删除分支节点 左子树不为空 右子树空 找左子树最大节点
  78. public TreeNode findLeftTree(TreeNode root, TreeNode pre){
  79. //System.out.print("以"+root.val+"为根节点的树的最大节点为");
  80. while(root.right != null){
  81. pre = root;
  82. root = root.right;
  83. }
  84. //System.out.println(root.val+"target节点为"+pre.val);
  85. return pre;
  86. }
  87. // pre为待删除分支节点 右子树不为空 找右子树最小节点
  88. public TreeNode findRightTree(TreeNode root, TreeNode pre){
  89. //System.out.print("以"+root.val+"为根节点的树的最大节点为------");
  90. while(root.left != null){
  91. pre = root;
  92. root = root.left;
  93. }
  94. //System.out.println(root.val+"它的pre节点为"+pre.val);
  95. return pre;
  96. }
  97. }

lieetcode 上看到一个思路

如果目标节点大于当前节点值,则去右子树中删除;
如果目标节点小于当前节点值,则去左子树中删除;
如果目标节点就是当前节点,分为以下三种情况:
其无左子:其右子顶替其位置,删除了该节点;
其无右子:其左子顶替其位置,删除了该节点;
其左右子节点都有:其左子树转移到其右子树的最左节点的左子树上,然后右子树顶替其位置,由此删除了该节点。

总结

  1. 头脑中要有一棵树,树形象上的特点,遍历序列上的特点
  2. 一定要先想清楚代码逻辑、循环逻辑、递归逻辑再继续
  3. 我的做题思维通常都是用代码模拟人脑

常用变量名增量更新

size、val、ans、cnt、cur、pre、next、left、right、index、gap、tar、res、src、len、start、end、flag、ch

代码随想录算法训练营day22 | leetcode 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入操作 ● 450.删除二叉搜索树中的节点的更多相关文章

  1. [程序员代码面试指南]二叉树问题-在二叉树中找到两个节点的最近公共祖先、[LeetCode]235. 二叉搜索树的最近公共祖先(BST)(非递归)

    题目 题解 法一: 按照递归的思维去想: 递归终止条件 递归 返回值 1 如果p.q都不在root为根节点的子树中,返回null 2 如果p.q其中之一在root为根节点的子树中,返回该节点 3 如果 ...

  2. LeetCode 235. 二叉搜索树的最近公共祖先 32

    235. 二叉搜索树的最近公共祖先 235. Lowest Common Ancestor of a Binary Search Tree 题目描述 给定一个二叉搜索树,找到该树中两个指定节点的最近公 ...

  3. LeetCode 235. 二叉搜索树的最近公共祖先

    235. 二叉搜索树的最近公共祖先 题目描述 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先 ...

  4. Leetcode:235. 二叉搜索树的最近公共祖先

    Leetcode:235. 二叉搜索树的最近公共祖先 Leetcode:235. 二叉搜索树的最近公共祖先 Talk is cheap . Show me the code . /** * Defin ...

  5. Java实现 LeetCode 235 二叉搜索树的最近公共祖先

    235. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个 ...

  6. 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

    剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q ...

  7. 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 + 二叉排序树 + 最近公共祖先

    剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 Offer_68_1 题目描述 方法一:迭代法 由于该题的二叉树属于排序二叉树,所以相对较简单. 只需要判断两个结点是否在根节点的左右子树中 ...

  8. [LeetCode] 235. Lowest Common Ancestor of a Binary Search Tree 二叉搜索树的最近公共祖先

    Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BS ...

  9. leetcode 235. 二叉搜索树的最近公共祖先(c++)

    给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先且 x ...

  10. 利用Tarjan算法解决(LCA)二叉搜索树的最近公共祖先问题——数据结构

    相关知识:(来自百度百科)  LCA(Least Common Ancestors) 即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 例如: 1和7的最近公共祖先为5: 1和5的 ...

随机推荐

  1. 深入浅出学习透析 Nginx 服务器的基本原理和配置指南「运维操作实战篇」

    Nginx前提回顾 Nginx 是一个高性能的 Web 和反向代理服务器, 它具有有很多非常优越的特性: Web服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效 ...

  2. mq中如何保证消息的顺序性

    先说结论 不建议在mq当中使用消息的投递顺序来保证消息的顺序一致性 反思为什么需要保留消息的顺序性 日常思维中,顺序大部分情况会和时间关联起来,即时间的先后表示事件的顺序关系.消息队列中的若干消息如果 ...

  3. 【Java SE】Day08 String类、static关键字、Arrays类、Math类

    一.String类 1.概述 所有双引号字符串,都是String类的对象 字符串常量,会存在字符串常量池中 2.创建 构造函数--空构造.字符数组.字节(byte ASCII码)数组 3.常用方法-- ...

  4. 5V升压8.4V,5V转8.4芯片电路图

    PW5300是电流模式升压DC-DC转换器.其内置0.2Ω功率MOSFET的PWM电路使该稳压器具有效高的功率效率.内部补偿网络还可以程度地减少了6个外部元件的数量.误差放大器的同相输入接到0.6V精 ...

  5. hook 无限debugger(猿人学第十四题)

    猿人学第十四题 检测太多了,debugger  fiddler替换无法实现.置空也不行.推荐使用hook  Function原生的构造 var func_ = Function.prototype.c ...

  6. 异常处理语法结构、yield生成器及其表达式

    今日内容回顾 目录 今日内容回顾 异常处理语法结构 异常处理实战应用 生成器对象 自定义range功能 yield冷门用法 yield与return对比 生成器表达式 笔试题 异常处理语法结构 异常处 ...

  7. Blazor组件自做十二 : Blazor Pdf Reader PDF阅读器 组件 (新版 7.1 移除pdfobject)

    Blazor Pdf Reader PDF阅读器 组件 示例: https://www.blazor.zone/PdfReaders https://blazor.app1.es/pdfReaders ...

  8. Django重点及面试题

    Django 简述python三大主流web框架 """ django 大而全,类似于航空母舰 但是有时候过于笨重 flask 小而精,类似于游骑兵(单行代码就可以起一个 ...

  9. 沁恒微(WCH)CH395/392配置使用,代码指南 网路接口芯片 CH395 CH392

    CH395/CH392相关资料可以从官网下载具体连接可以看博客:WCH以太网相关芯片资料总结 里面是WCH官网相关信息的链接. 也可以去Gitee上下载:Gitee链接. STM32控制CH395的例 ...

  10. appium基本使用(Android)

    一.环境搭建 详情可见:https://www.cnblogs.com/lihongtaoya/p/16971096.html 二.元素定位 详情可见:https://www.cnblogs.com/ ...