• 算法day22|235,701,450


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

    1. class Solution:
    2. def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
    3. #左右中,使用后序遍历
    4. #终止条件
    5. if root is None:
    6. return root
    7. #如果根节点的值为q或者p,那么返回节点
    8. if root == q or root == p:
    9. return root
    10. #单层逻辑
    11. #左右中
    12. #需要有返回值,因为需要传递节点
    13. left = self.lowestCommonAncestor(root.left,p,q)
    14. right = self.lowestCommonAncestor(root.right,p,q)
    15. if left is None and right is None:
    16. return None
    17. if left is None and right is not None:
    18. return right
    19. elif left is not None and right is None:
    20. return left
    21. else:
    22. return root

    三天后写出来了,说明ac了呜呜呜

    相对于 二叉树的最近公共祖先 本题就简单一些了,因为 可以利用二叉搜索树的特性。

    使用二叉树的特性,不需要全部都遍历,根节点的数值永远都比左子树的大,永远都比右子树的小

    迭代法:

    1. class Solution:
    2. def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
    3. #迭代法
    4. while root:
    5. if root.val > p.val and root.val > q.val:
    6. root = root.left
    7. elif root.val < p.val and root.val < q.val:
    8. root = root.right
    9. else:
    10. return root

    递归法:

    1. class Solution:
    2. def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
    3. def traversal(root,p,q):
    4. #递归法
    5. #终止条件
    6. if root is None:
    7. return root
    8. #单层逻辑
    9. #左边
    10. if root.val > p.val and root.val >q.val:
    11. left = traversal(root.left,p,q)
    12. if left is not None:
    13. return left
    14. #右边
    15. if root.val < p.val and root.val
    16. right = traversal(root.right,p,q)
    17. if right is not None:
    18. return right
    19. return root
    20. return traversal(root,p,q)

    二刷:

    (未ac) 哭了,没有真正掌握

    1. var lowestCommonAncestor = function(root, p, q) {
    2. const find = function(root,p,q){
    3. // 终止条件
    4. if(root === null){
    5. return null
    6. }
    7. // 往左递归
    8. if(root.val > q.val && root.val > p.val){
    9. let left = find(root.left,p,q)
    10. if(left != null){
    11. return left
    12. }
    13. }
    14. // 往右递归
    15. else if(root.val < q.val && root.val < p.val){
    16. let right = find(root.right,p,q)
    17. if(right != null){
    18. return right;
    19. }
    20. }else{
    21. // 如果在中间,根节点就是它的结果
    22. return root;
    23. }
    24. }
    25. return find(root,p,q)
    26. };

    迭代法

    1. var lowestCommonAncestor = function(root, p, q) {
    2. // 迭代法
    3. while(root){
    4. if(root.val > p.val && root.val > q.val){
    5. root = root.left
    6. }else if(root.val < p.val && root.val < q.val){
    7. root = root.right
    8. }else{
    9. return root
    10. }
    11. }
    12. return null
    13. };

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

    1. class Solution:
    2. def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
    3. #终止条件
    4. if root is None:
    5. newNode = TreeNode(val)
    6. return newNode
    7. #单层遍历
    8. if root.val < val:
    9. root.right = self.insertIntoBST(root.right,val)
    10. if root.val > val:
    11. root.left = self.insertIntoBST(root.left,val)
    12. return root

    题目并没有要求需要改变树的结构,所以只需要将节点插入叶子节点上。添加节点不需要改二叉树的结构

    题目链接/文章讲解:代码随想录

    视频讲解:原来这么简单? | LeetCode:701.二叉搜索树中的插入操作_哔哩哔哩_bilibili

    二刷:(未ac)

    迭代无返回值方法,这种方法更直观,更容易一下子想到

    1. var insertIntoBST = function(root, val) {
    2. const find = function(cur,val){
    3. // 如果遇到叶子节点,将值插入
    4. if(cur === null){
    5. let newNode = new TreeNode(val);
    6. if(pre.val > val){
    7. pre.left= newNode;
    8. }else{
    9. pre.right= newNode;
    10. }
    11. return ;
    12. }
    13. // 记录上一个节点为父节点
    14. pre = cur;
    15. if(val > cur.val){
    16. find(cur.right,val);
    17. }
    18. if(val < cur.val){
    19. find(cur.left,val);
    20. }
    21. }
    22. if(root === null){
    23. return new TreeNode(val);
    24. }
    25. // 先记录当前节点为空
    26. let pre = null;
    27. find(root,val);
    28. return root;
    29. };

    递归法有返回值

    1. var insertIntoBST = function(root, val) {
    2. const find = function(cur,val){
    3. // 终止条件
    4. if(cur === null){
    5. let newNode = new TreeNode(val);
    6. return newNode;
    7. }
    8. if(val<cur.val){
    9. cur.left = find(cur.left,val)
    10. }
    11. if(val>cur.val){
    12. cur.right = find(cur.right,val)
    13. }
    14. return cur;
    15. }
    16. if(root === null){
    17. return new TreeNode(val);
    18. }
    19. return find(root,val);
    20. };

    迭代法

    1. var insertIntoBST = function(root, val) {
    2. // 迭代法
    3. if(root === null){
    4. return new TreeNode(val);
    5. }
    6. let cur = root;
    7. let pre = null;
    8. while(cur){
    9. // 移动前记录一下上一个节点的值
    10. pre = cur
    11. if(cur.val > val){
    12. cur = cur.left;
    13. }else{
    14. cur = cur.right;
    15. }
    16. }
    17. // 如果找到了
    18. if(pre.val > val){
    19. pre.left = new TreeNode(val);
    20. }else{
    21. pre.right = new TreeNode(val);
    22. }
    23. return root;
    24. };

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

    1. class Solution:
    2. def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
    3. #终止条件
    4. #当没有找到删除的点
    5. if root is None:return None
    6. #当找到删除的点
    7. if root.val == key:
    8. #如果是叶子节点
    9. if root.left is None and root.right is None:
    10. return None
    11. #如果非叶子节点
    12. elif root.left is not None and root.right is None:
    13. return root.left
    14. elif root.left is None and root.right is not None:
    15. return root.right
    16. else:
    17. cur = root.right
    18. #需要一直遍历到左边最小的数
    19. while cur.left:
    20. cur = cur.left
    21. cur.left = root.left
    22. #删除节点
    23. return root.right
    24. #左
    25. if key < root.val:
    26. root.left = self.deleteNode(root.left,key)
    27. #右
    28. if key > root.val:
    29. root.right = self.deleteNode(root.right,key)
    30. #返回子树
    31. return root

    分两种情况:

    没找到删除的点

    找到了删除的点

            删除叶子节点

            删除非叶子节点

                    左为空,右不为空

                    左为不空,右为空

                    左不空,右不空

                            最为复杂,需要满足BTS的特征,所以需要找到右子树的最大的数

    中间的处理逻辑是这样的

    题目链接/文章讲解:代码随想录

    视频讲解:调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点_哔哩哔哩_bilibili

     二刷:递归法(未ac)

    1. var deleteNode = function (root, key) {
    2. // 终止条件
    3. //如果啥都没找到就返回null
    4. if (root === null) {
    5. return null;
    6. }
    7. //分五种情况
    8. if (root.val === key) {
    9. if (root.left !== null && root.right === null) {
    10. return root.left;
    11. } else if (root.left === null && root.right !== null) {
    12. return root.right;
    13. } else if (root.left === null && root.right === null) {
    14. //都为空
    15. return null;
    16. } else {
    17. let cur = root.right;
    18. // 找右子树的左叶子节点
    19. while (cur.left !== null) {
    20. cur = cur.left;
    21. }
    22. cur.left = root.left;
    23. root = root.right;
    24. return root;
    25. }
    26. }
    27. if (root.val > key) {
    28. root.left = deleteNode(root.left, key);
    29. }
    30. if (root.val < key) {
    31. root.right = deleteNode(root.right, key);
    32. }
    33. return root;
    34. };

     

  • 相关阅读:
    爬网神器组
    Kafka To HBase To Hive
    基于springboot+vue的纺织品企业财务管理系统
    JavaScript:实现binarySearch二分查找算法(附完整源码)
    Spring 的 @Transactional 如何实现的?
    【ES实战】ES主副分片数据不一致分析
    C++ 测试框架 GoogleTest 初学者入门篇 丙
    鸿运主动安全云平台任意文件下载漏洞
    微信小程序开发开篇词 自顶向下,云端赋能:小程序的高效开发之道
    MySQL安装与配置
  • 原文地址:https://blog.csdn.net/weixin_42173016/article/details/127939179