代码随想录算法训练营第二十天|235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点

写在前边的话

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

题目链接

        力扣题目链接

题目难度

        中等

看到题目的第一想法

        看到题目的第一想法,除了昨天做过的普通二叉树的最近祖先的解法利用回溯从底向上搜索,我会想到使用迭代法,但我好像不太会使用到二叉树搜索树的特性,我是选择的层序遍历。得转换下思维了。

python

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root:
            return root

        queue = collections.deque([root])
        while queue:
            n = len(queue)
            for i in range(n):
                node = queue.popleft()
                if min(p.val, q.val) <= node.val <= max(p.val, q.val):
                    return node
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return None

       

看完代码随想录的总结

文章讲解

        代码随想录文章讲解

视频讲解

        代码随想录视频讲解

解题思路

        1. 递归法:由于没有中节点的逻辑所以前中后序都是可以的。

           递归三步曲:

           1)入参:根节点,p,q;返回值:满足条件的二叉树节点。

           2)终止条件:节点空返回空

           3)单次递归逻辑:如果节点小于p,q那么就向右子树遍历;如果节点值大 于p,q那么就向左子树遍历;否则就返回当前节点。

        2. 迭代法

            从根节点开始遍历,如果当前节点小于p,q那么就向右子树搜索;如果当前节点值大于p,q那么就像左子树搜索;否则返回当前节点。

代码编写
python
# 递归法
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root:
            return root

        print(root.val)

        if root.val < p.val and root.val < q.val:
            right_res = self.lowestCommonAncestor(root.right, p, q)
            if right_res:
                return right_res
        
        if root.val > p.val and root.val > q.val:
            left_res = self.lowestCommonAncestor(root.left, p, q)
            if left_res:
                return left_res

        return root

#********************************************************************************

# 迭代法
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        cur = root
        while cur:
            if cur.val < p.val and cur.val < q.val:
                cur = cur.right
            elif cur.val > p.val and cur.val > q.val:
                cur = cur.left
            else:
                return cur
        return None
java

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

题目链接

        力扣题目链接

题目难度

        中等

看到题目的第一想法

        看到题目的第一想法是想用迭代法,在遍历节点的时候找到要插入的位置。

        python

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        node = TreeNode(val)
        if not root:
            return node

        cur = root
        while True:
            if val < cur.val:
                print(cur.val)
                if not cur.left:   
                    cur.left = node
                    return root
                else:
                    cur = cur.left

            if val > cur.val:
                if not cur.right:
                    node = TreeNode(val)
                    cur.right = node
                    return root
                else:
                    cur = cur.right

看完代码随想录的总结

文章讲解

        代码随想录文章讲解

视频讲解

        代码随想录视频讲解

解题思路

        1.递归法:需要记录父节点(方案一:可以通过递归函数的返回值完成父子节点的赋值这种方法比较便利,方案二:另外也可以找到要插入父节点位置以后再判断是插入到左节点还是右节点)

          递归三步曲方案一:

          入参:当前节点以及要比较的数值,返回值要插入的节点。

          终止条件:节点空则返回要插入的节点。

          单次递归逻辑:赋值当前节点给父节点;如果节点值大于要比较的值,那么向左子树遍历;如果当前节点值小于要比较的值,那么向右子树遍历。注意这里返回值会赋值给左右子节点。

           递归三步曲方案二:

          入参:当前节点以及要比较的数值,无返回值。

          终止条件:节点空即下层左节点或者右节点为空了,这个时候由于递归函数没有返回值,所以需要检查比较值是大于父节点还是小于父节点,小于插入到左节点,大于插入到右节点。

          单次递归逻辑:赋值当前节点给父节点;如果节点值大于要比较的值,那么向左子树遍历;如果当前节点值小于要比较的值,那么向右子树遍历。

代码编写
python
#方案一
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.parent  = None
    def reversal(self, cur, val):
        if not cur:
            node = TreeNode(val)
            return node

        if cur.val > val:
            cur.left = self.reversal(cur.left, val)
        else:
            cur.right = self.reversal(cur.right, val)
        return cur  # 注意这里要一层一层返回最终返回的就是根节点了

    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:
            return TreeNode(val)
        cur = root
        return self.reversal(cur, val)

#********************************************************************

# 方案二
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.parent  = None
    def reversal(self, cur, val):
        if not cur:
            node = TreeNode(val)
            if self.parent.val > val:
                self.parent.left = node
            else:
                self.parent.right = node
            return

        self.parent = cur
        if cur.val > val:
            self.reversal(cur.left, val)
        else:
            self.reversal(cur.right, val)

    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:
            return TreeNode(val)
        cur = root
        self.reversal(cur, val)
        return root

# ***********************************************************************

# 迭代法
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        node = TreeNode(val)

        if not root:
            return TreeNode(val)
        
        cur = root
        while cur:
            parent = cur
            if cur.val > val:
                cur = cur.left
            else:
                cur = cur.right

        if parent.val > val:
            parent.left = node
        else:
            parent.right = node

        return root
java

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

题目链接

        力扣题目链接

题目难度

        中等

看到题目的第一想法

        没接触过,看到就觉得有点难!

看完代码随想录的总结

文章讲解

        代码随想录文字讲解

视频讲解

        代码随想录视频讲解

解题思路

        1. 递归法(关键单层递归中的情况梳理)

            递归三步曲:

            1)入参:根节点和要比较的值;返回值:删除节点以后要返回的节点(用于上一层递归来赋值)。

            2)终止条件:有五种情况:第一种:节点空则返回空,说明没找到要删除的节点;第二种:遍历到的要删除的节点此时左右节点均为空,那么直接返回空;第三种:遍历到要删除的节点此时左节点不为空右节点为空,那么直接返回左节点;第四种情况:遍历到要删除的节点此时左节点空右节点不为空,那么直接返回右节点;第五种:遍历到要删除的节点了此时左右子节点都不为空,此时需要把左子树放到右子树当中(将删除节点的左子树头结点放到删除节点的右子树的最左面节点的左孩子上),整个时候就成了左节点空右节点非空的情况,返回右节点。

            3)单层递归逻辑:遍历左子树,遍历右子树,如果不满足上边终止条件则返回当前节点。

代码编写
python
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def reversal(self, root, key):
        if not root:
            return root

        if root.val == key:
            if not root.left and not root.right:
                return None
            elif root.left and not root.right:
                return root.left
            elif not root.left and root.right:
                return root.right
            else:
                cur = root.right
                while(cur.left):
                    cur = cur.left
                cur.left = root.left
                return root.right
        
        if root.val > key:
            root.left = self.reversal(root.left, key)
        else:
            root.right = self.reversal(root.right, key)

        return root

    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        return self.reversal(root, key)
java

今日总结

        今天的题目也都是二叉搜索树的题目,做二叉搜索树的题目,还是要注意利用其特性。在删除和插入二叉树节点的时候使用递归,可以利用返回值进行节点赋值的操作,这样比较简单不用重复去判断条件。

  • 30
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值