代码随想录算法训练营第十八天|530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先

写在前边的话

        今天是二叉树训练的第六天啦,感觉这一周都是追赶进度的一周哈哈,还是基础不牢固呀,基础理论见下边链接,无论如何也要坚持下去,加油呀!

        二叉树基础理论

530.二叉搜索树的最小绝对

题目链接

        力扣题目链接

题目难度

         简单

看到题目的第一想法

        有了昨天验证二叉搜索树的题目训练,看到这道题目的时候就会想到也使用递归+双指针的思路解决。

        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.pre = None
        self.res = float('inf') 
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        if not root:
            return

        self.getMinimumDifference(root.left)

        if self.pre:
            self.res =  min(root.val - self.pre.val, self.res)

        self.pre = root

        self.getMinimumDifference(root.right)

        return self.res

看完代码随想录之后的总结

文章讲解

          代码随想录文章讲解

视频讲解

        代码随想录视频讲解

解题思路

        1. 递归+双指针:递归顺序中序遍历(根据二叉搜索树的有序性,采用中序遍历的话,求整个二叉树节点差值的最小值,其实就是求中序遍历中相邻节点的最小值)。

        2.递归三步曲:

           1)入参:根节点,返回值无

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

           3)单层递归逻辑:主要是中的处理逻辑是、要先检查前一个节点是不是为空,不为空的话就计算当前节点和前一个节点的差值,并和返回值做比较。

代码编写
python

        卡哥的代码和我写的思路一样,就是递归的算法单独写了一个方法。

class Solution:
    def __init__(self):
        self.result = float('inf')
        self.pre = None

    def traversal(self, cur):
        if cur is None:
            return
        self.traversal(cur.left)  # 左
        if self.pre is not None:  # 中
            self.result = min(self.result, cur.val - self.pre.val)
        self.pre = cur  # 记录前一个
        self.traversal(cur.right)  # 右

    def getMinimumDifference(self, root):
        self.traversal(root)
        return self.result
java 

501.二叉搜索树中的众数

题目链接

        力扣题目链接

题目难度

        简单

看到题目的第一想法

        看到题目的第一想法我会用迭代法,采用层序遍历节点,然后以键值对的形式保存节点数据以及出现的次数,然后再找到出现次数最多的数据。

# 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 findMode(self, root: Optional[TreeNode]) -> List[int]:
        dic = {}
        res = set()
        queue = collections.deque([root])
        max_freq = float("-inf")
        while queue:
            n = len(queue)
            for i in range(n):
                node = queue.popleft()
                dic[node.val] = dic.get(node.val, 0) + 1
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        for key, freq in dic.items():
            max_freq = max(max_freq, freq)

        for key, freq in dic.items():
            if freq == max_freq:
                res.add(key)
        return list(res)

注意:没有用到二叉搜索树的特性。 

看完代码随想录之后的总结

文章讲解

       代码随想录文章讲解

视频讲解

        代码随想录视频讲解

解题思路

        1. 递归+双指针:中序遍历,一次遍历。

        2. 递归三部曲:

            1)入参:根节点;返回值:无。

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

            3)  单次递归逻辑:中序遍历;主要是中节点的处理,首先要对维护节点频率的变量freq进行维护,确认需要变更的逻辑(如果前一个节点空则表示当前节点为第一个节点freq=1;如果当前节点等于前一个节点freq就加一;如果与前一个节点不同了freq=1);其次就是要更新前一个节点为当前节点;最后就是要对最大频率max_freq以及最终结果数组res的一个处理(freq等于最大频率max_freq,那么要将当前节点添加到res中;如果freq大于了max_freq说明之前res中存储的数据都不能满足了,那么需要清空数组,并把当前节点值放进res中,然后更新max_freq)。

代码编写
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.max_freq = 0
        self.res = []
        self.freq = 0
        self.pre = None
    def reversal(self, cur):
        if not cur:
            return

        self.reversal(cur.left)  # 左

        # 中
        if not self.pre:
            self.freq = 1
        elif cur.val == self.pre.val:
            self.freq += 1
        else:
            self.freq = 1

        self.pre = cur

        if self.freq == self.max_freq:
            self.res.append(cur.val)
        if self.freq > self.max_freq:
            self.res.clear()
            self.res.append(cur.val)
            self.max_freq = self.freq

        # 右
        self.reversal(cur.right)

    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        self.reversal(root)
        return self.res
java 

236. 二叉树的最近公共祖先

题目链接

         力扣题目链接                

题目难度

        中等

看到题目的第一想法

        感觉有点难,没什么好的想法。

看完代码随想录之后的总结

文章讲解

        代码随想录文章讲解

视频讲解

        代码随想录视频讲解

解题思路

        1. 递归法:后序遍历

        2. 递归三步曲:

            1)入参:根节点、p、q;返回值:公共祖先。

            2)终止条件:节点为空返回空;节点等于p或等于q返回当前节点。

            3)单次递归逻辑:后序遍历,主要是中的处理逻辑。如果左右节点返回的结果都不为空那么当前节点就为要找的公共祖先;如果左节点返回结果为空右节点返回结果不为空,那么继续向上返回右节点返回的结果;同理如果左节点返回结果非空而右节点返回节点空的话,那么继续向上返回左节点返回的结果;如果左右节点返回结果均为空的话那么继续向上返回的结果也为空。(注意这个处理逻辑其实是包含了p/q某个节点为祖先的情况的,如果p为祖先这种情况遍历到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

        if root == p or root == q:
            return root

        left_res = self.lowestCommonAncestor(root.left, p, q)
        right_res = self.lowestCommonAncestor(root.right, p, q)

        if left_res and right_res:
            return root
        elif not left_res and right_res:
            return right_res
        elif left_res and not right_res:
            return left_res
        else:
            return None
java 

今日总结

        今天一部分的训练还是针对二叉搜索树的,在解决二叉搜索树的问题:1.一般用中序遍历 2. 要利用二叉搜索树的特性,采用中序遍历的话,节点值是单调递增的,因此可以采用将节点值保存在数组中然后解题;也可以采用递归+双指针的思路解题,解题过程中要注意代码处理的技巧(比如二叉搜索树众数的解题过程中我们需要清空结果数组的这个逻辑)。另一部分是二叉树公共祖先的题目,由于找的是公共祖先因此是需要先判断左右子节点的情况然后才能确定中节点的情况,因此要采用后序遍历的顺序(这个题目要想到p/q一方为祖先的情况)。

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值