二叉树-构建二叉树:中后序构建二叉树/前中序构建二叉树/最大二叉树/合并二叉树/二叉搜索树/最近公共祖先/

前中、中后可以确定唯一二叉树,前后不可以。因为没有中序遍历无法确定左右部分,也就是无法分割。
在这里插入图片描述

106.从中序与后序遍历序列构造二叉树

在这里插入图片描述
思路:
在这里插入图片描述
说到一层一层切割,就应该想到了递归

来看一下一共分几步:

第一步:如果数组大小为零的话,说明是空节点了。

第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点

第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)

第五步:切割后序数组,切成后序左数组和后序右数组(中左和后左 中右和后右 长度是一样 所以可以根据切割的中序的长度来分)

第六步:递归处理左区间和右区间

 
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def buildTree(self, inorder, postorder):
        """
        :type inorder: List[int]
        :type postorder: List[int]
        :rtype: TreeNode
        """
        # 第一步: 特殊情况讨论: 树为空. (递归终止条件)
        if not postorder:
            return None
        
        # 第二步: 后序遍历的最后一个就是当前的中间节点. 
        root_val = postorder[-1]
        root = TreeNode(root_val)
        
        # 第三步: 找切割点. 
        separator_index  = inorder.index(root_val)

        # 第四步: 切割inorder数组. 得到inorder数组的左,右半边. 
        inorder_left = inorder[:separator_index]
        inorder_right = inorder[separator_index + 1:]

        
        # 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
        # ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的. 
        postorder_left = postorder[:len(inorder_left)]
        postorder_right = postorder[len(inorder_left):len(postorder) - 1]

        #第六步 递归
        root.left = self.buildTree(inorder_left, postorder_left)
        root.right = self.buildTree(inorder_right, postorder_right)

        return root 
 

105.从前序与中序遍历序列构造二叉树

在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        # 1树空 条件终止
        if not preorder:
            return None
        
        # 2找前序第一个
        root_val = preorder[0]
        root = TreeNode(root_val)

        # 3 在中序中找分割点
        separator_index = inorder.index(root_val)


        # 4分割中序
        inorder_left =  inorder[:separator_index]
        inorder_right = inorder[separator_index + 1:]

        # 5分割前序 长度于中序同
        preorder_left = preorder[1:len(inorder_left) + 1]
        preorder_right = preorder[len(inorder_left) + 1:]

        # 6递归

        root.left = self.buildTree(preorder_left, inorder_left)
        root.right = self.buildTree(preorder_right,inorder_right)

        return root 

654最大二叉树

在这里插入图片描述
思路:前序 :因为先选出最大值构建根节点 不断分两部分 每次选出最大值作为新的根 —递归

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def constructMaximumBinaryTree(self, nums):
        """
        :type nums: List[int]
        :rtype: TreeNode
        """
        if not nums:
            return None
        
        # 找到最大值和下标值
        maxvalue = max(nums)
        index  = nums.index(maxvalue)
        root = TreeNode(maxvalue)

        #分割数组
        left = nums[:index]
        right = nums[index + 1:]

        root.left = self.constructMaximumBinaryTree(left)
        root.right = self.constructMaximumBinaryTree(right)

        return root 

617.合并二叉树

在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def mergeTrees(self, root1, root2):
        """
        :type root1: TreeNode
        :type root2: TreeNode
        :rtype: TreeNode
        """
        # 递归终止条件
         #  但凡有一个节点为空, 就立刻返回另外一个. 如果另外一个也为None就直接返回None. 
        if not root1:
            return root2
        if not root2:
            return root1
            
        # 单层逻辑 前序
        root1.val += root2.val #中
        root1.left = self.mergeTrees(root1.left, root2.left)# 左
        root1.right = self.mergeTrees(root1.right, root2.right)# 右
        
        # ⚠️ 注意: 本题我们重复使用了题目给出的节点而不是创建新节点. 节省时间, 空间.  直接在root1上修改
        return root1

700.二叉搜索树中的搜索在这里插入图片描述

思路:
二叉搜索树是一个有序树:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉搜索树
这就决定了,二叉搜索树,递归遍历和迭代遍历和普通二叉树都不一样。

因为搜索到目标节点了,就要立即return了,这样才是找到节点就返回(搜索某一条边),如果不加return,就是遍历整棵树了。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def searchBST(self, root, val):
        """
        :type root: TreeNode
        :type val: int
        :rtype: TreeNode
        """
        # 为什么要有返回值: 
        #   因为搜索到目标节点就要立即return,
        #   这样才是找到节点就返回(搜索某一条边),如果不加return,就是遍历整棵树了。
        
        # 递归结束条件
        if not root or root.val == val: 
            return root

        if root.val > val: 
            return self.searchBST(root.left, val)

        if root.val < val: 
            return self.searchBST(root.right, val)

        

98.验证二叉搜索树

在这里插入图片描述
要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列。

有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。

# 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 isValidBST(self, root: Optional[TreeNode]) -> bool:
        # 思路: 利用BST中序遍历的特性.
        # 中序遍历输出的二叉搜索树节点的数值是有序序列

        candidate = []
        
        #打印中序的数组
        def __traverse(root):
            nonlocal candidate
            if not root:
                return
            __traverse(root.left)
            candidate.append(root.val)
            __traverse(root.right)

        def __issorted(nums):
            for i in range(1,len(nums)):
                if nums[i] <= nums[i - 1]:
                    return False
            
            return True
        
        __traverse(root)
        res = __issorted(candidate)

        return res

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

在这里插入图片描述
注意是二叉搜索树,二叉搜索树可是有序的。

遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。

#递归

# 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 getMinimumDifference(self, root: TreeNode) -> int:
        candicate = []
        def __traversal(root):
            nonlocal candicate
            if not root:
                return

            __traversal(root.left)
            candicate.append(root.val)
            __traversal(root.right)

        def __findmin(nums):
            minval = nums[1] - nums[0]
            for i in range(1,len(nums)):
                if nums[i] - nums[i - 1] < minval:
                    minval = nums[i] - nums[i - 1]
            return minval
        
        __traversal(root)
        res = __findmin(candicate)
        return res    

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: TreeNode) -> List[int]:
        candicate = []
        res = []
        def __traversal(root):
            nonlocal candicate
            if not root:
                return

            __traversal(root.left)
            candicate.append(root.val)
            __traversal(root.right)

        def __findmost(nums):
            nonlocal res
            dict = {}
            for x in nums:
                if x in dict:
                    dict[x] += 1
                else:
                    dict[x] = 1
            maxvalue = max(dict.values())
            # 注意items是key value
            for k,v in dict.items():
                if v == maxvalue:
                    res.append(k)
            return res
        
        
        __traversal(root)
        __findmost(candicate)
        return res   

遍历一遍二叉树

# 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 = TreeNode()
        self.count = 0
        self.max_count = 0
        self.result = []

    def findMode(self, root: TreeNode) -> List[int]:
        if not root: return None
        self.search_BST(root)
        return self.result
        
    def search_BST(self, cur: TreeNode) -> None:
        if not cur: return None
        self.search_BST(cur.left) # 左
        # 第一个节点 中
        if not self.pre:
            self.count = 1
        # 与前一个节点数值相同
        elif self.pre.val == cur.val:
            self.count += 1 
        # 与前一个节点数值不相同
        else:
            self.count = 1
        self.pre = cur

        if self.count == self.max_count:
            self.result.append(cur.val)
        
        if self.count > self.max_count:
            self.max_count = self.count
            self.result = [cur.val]	# 清空self.result,确保result之前的的元素都失效
        
        self.search_BST(cur.right)# 右

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

在这里插入图片描述
如果递归函数有返回值,如何区分要搜索一条边,还是搜索整个树呢?

搜索一条边的写法:

if (递归函数(root->left)) return ;

if (递归函数(root->right)) return ;

搜索整个树写法:

left = 递归函数(root->left);
right = 递归函数(root->right);
left与right的逻辑处理;

在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)

https://programmercarl.com/0236.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html

没看懂 = =

    """二叉树的最近公共祖先 递归法"""

    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root or root == p or root == q:
            return root
        
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        
        if left and right:
            return root
        if left:
            return left
        return right

235. 二叉搜索树的最近公共祖先在这里插入图片描述

在有序树里,如果判断一个节点的左子树里有p,右子树里有q呢?

其实只要从上到下遍历的时候,cur节点是数值在[p, q]区间中则说明该节点cur就是最近公共祖先了。

# 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 root.val > p.val and root.val > q.val:
            return self.lowestCommonAncestor(root.left, p, q)
        
        # 过小 应该在右子树找
        if root.val < p.val and root.val < q.val:
            return self.lowestCommonAncestor(root.right, p, q)

        # 在区间内 返回root
        else:
            return root
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值