树(5)-----判断两颗树一样或者一棵树是否是另外一颗的子树

本文详细介绍了二叉树的相关算法,包括如何判断两棵二叉树是否相同、判断一棵树是否为另一棵树的子树及寻找重复子树等问题,并提供了具体的Python实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、判断两颗树是否一样。(递归)

        def isSameTree(p,q):
            if not p and not q:
                return True
            elif not p and q or (not q and p):
                return False
            else:
                if p.val!=q.val:
                    return False
                else:
                    return isSameTree(p.left,q.left) and isSameTree(p.right,q.right)

2、判断一颗树是否为另外一颗的子树:【在判断是否一样树之上还加一层循环】(递归加循环)

    def isSubtree(self, s, t):
        """
        :type s: TreeNode
        :type t: TreeNode
        :rtype: bool
        """
        def isSameTree(p,q):
            if not p and not q:
                return True
            elif not p and q or (not q and p):
                return False
            else:
                if p.val!=q.val:
                    return False
                else:
                    return isSameTree(p.left,q.left) and isSameTree(p.right,q.right)
        prev=[s]
        while prev:
            node=prev.pop()
            if node:
                if isSameTree(node,t):
                    return True
                prev.extend([node.left,node.right])

法二:转化成字符串,判断字符串1是否在字符串2之中。

def isSubtree(s, t):

    def convert(tree):
        stack = [tree]
        string = ''
        while stack:
            node = stack.pop()
            if node:
                string += '#' + str(node.val)
                stack.extend((node.left, node.right))
            else:
                string += '$'
        return string

    strings = convert(s)
    stringt = convert(t)

    return stringt in strings

 3、寻找重复的子树

给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。

两棵树重复是指它们具有相同的结构以及相同的结点值。

示例 1:

        1
       / \
      2   3
     /   / \
    4   2   4
       /
      4

下面是两个重复的子树:

      2
     /
    4

    4

因此,你需要以列表的形式返回上述重复子树的根结点。

思路1:(先遍历所有的节点存在列表中,列表每个节点两两之间比较一下,是否是同一颗树,如果是就将该节点放入结果中,最后也要注意一下去重)【这个方法被我写得超出时间限制】

思路2:(先遍历所有的节点存在列表中,然后将每个节点对应的先序遍历存在另一个列表中,然后用一个字典存两个列表,先序遍历的列表作为key,节点列表作为value,若key有重复的,就将字典值加进结果,去重就可以了。)

from collections import defaultdict
class Solution(object):
    def findDuplicateSubtrees(self, root):
        """
        :type root: TreeNode
        :rtype: List[TreeNode]
        """


        #思路1:超出时间限制


        if not root:
            return []
        listNode=[]
        def isSameTree(p,q):
            if not p and not q:
                return True
            elif (p and not q) or (q and not p):
                return False
            else:
                if p.val!=q.val:
                    return False
                else:
                    return isSameTree(p.left,q.left) and isSameTree(p.right,q.right)                    
        prev=[root]
        while prev:
            node=prev.pop(0)
            if node:
                listNode.append(node)
                prev.extend([node.left,node.right])
        res=[]
        i=0
        
        while i < len(listNode):
            j=i+1
            flag=1
            while i+1 <= j < len(listNode):
                if isSameTree(listNode[i],listNode[j]):
                    if listNode[i] not in res:
                        res.append(listNode[i])
                    del listNode[j]
                    flag=0
                if flag:
                    j+=1
                flag=1
            i+=1
        return res
    

        #思路2


        if not root:
            return []
        def order(root):
            orderRes=[]
            prev=[root]
            while prev:
                node=prev.pop()
                if node:
                    orderRes.append(node.val)
                    prev.extend([node.left,node.right])
                else:
                    orderRes.append(None)
            return orderRes
        prev=[root]
        dic=defaultdict(TreeNode)
        res=[]
        while prev:
            node=prev.pop()
            if node:
                if tuple(order(node)) not in dic:
                    dic[tuple(order(node))]=node
                else:
                    res.append(dic[tuple(order(node))])
                prev.extend([node.left,node.right])
        return list(set(res))

 

转载于:https://www.cnblogs.com/Lee-yl/p/9133803.html

<think>我们面对的问题是如何将两棵合并成一棵树数据结构中的一种常见形式,合并操作通常需要根据的具体类型(如二叉、二叉搜索、普通等)和合并规则(如合并相同位置的节点、合并为新的结构等)来进行。由于问题没有指定的类型,我们将考虑几种常见情况。 常见的合并方法包括: 1. 递归合并:如果两棵结构相似(如同为二叉),可以递归地合并对应节点。 2. 遍历合并:通过遍历两棵,将节点收集起来,然后构建一棵新。 3. 特定类型的合并:如二叉搜索可以通过中序遍历得到有序数组,然后合并两个有序数组再重建二叉搜索。 由于问题描述较为宽泛,这里将介绍两种常见场景的合并方法:普通二叉的合并(节点值合并)和二叉搜索的合并。 ### 方法1:普通二叉的合并(对应位置节点值相加) 假设两棵二叉的结构相同(即对应位置都有节点或都没有节点),我们可以将对应节点的值相加。如果结构不同,可以在缺失的位置用0补充。 递归合并步骤: - 如果两棵都为空,返回空。 - 如果其中一棵树为空,则以0作为该节点的值,继续合并(或者直接使用另一棵树的节点,但这里我们要求合并节点值,所以用0)。 - 如果两个节点都存在,则新节点的值为两个节点值之和。 - 递归合并左子树和右子树。 示例代码(Python): ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def mergeTrees(t1, t2): if not t1 and not t2: return None val1 = t1.val if t1 else 0 val2 = t2.val if t2 else 0 new_val = val1 + val2 new_node = TreeNode(new_val) new_node.left = mergeTrees(t1.left if t1 else None, t2.left if t2 else None) new_node.right = mergeTrees(t1.right if t1 else None, t2.right if t2 else None) return new_node ``` ### 方法2:二叉搜索的合并 二叉搜索(BST)的中序遍历是有序的。合并两棵二叉搜索,可以分别得到它们的中序遍历序列,然后合并两个有序数组,再根据合并后的有序数组重建一棵二叉搜索。 步骤: 1. 对两棵BST分别进行中序遍历,得到两个有序数组。 2. 合并两个有序数组(归并排序的合并过程)。 3. 根据合并后的有序数组构建一棵平衡的BST(可以使用二分法递归构建)。 示例代码(Python): ```python def inorder(root, arr): if root: inorder(root.left, arr) arr.append(root.val) inorder(root.right, arr) def mergeSortedArrays(arr1, arr2): merged = [] i, j = 0, 0 while i < len(arr1) and j < len(arr2): if arr1[i] < arr2[j]: merged.append(arr1[i]) i += 1 else: merged.append(arr2[j]) j += 1 while i < len(arr1): merged.append(arr1[i]) i += 1 while j < len(arr2): merged.append(arr2[j]) j += 1 return merged def sortedArrayToBST(arr): if not arr: return None mid = len(arr) // 2 root = TreeNode(arr[mid]) root.left = sortedArrayToBST(arr[:mid]) root.right = sortedArrayToBST(arr[mid+1:]) return root def mergeBSTs(t1, t2): arr1 = [] arr2 = [] inorder(t1, arr1) inorder(t2, arr2) merged_arr = mergeSortedArrays(arr1, arr2) return sortedArrayToBST(merged_arr) ``` ### 方法3:普通的合并(基于子节点列表) 如果不是二叉,而是每个节点有多个子节点(如n叉),合并方法可以是: - 将两棵相同位置的节点合并(节点值相加或其他操作),然后递归合并它们的子节点。 - 需要处理子节点数量不一致的情况,可以以子节点数量多的那棵为基准,另一棵树缺失的位置用空节点代替。 由于普通的结构差异较大,具体实现需要根据的具体定义来调整。 ### 注意事项 - 在合并过程中,如果节点包含的数据不仅仅是数值(如还有其他属性),合并规则需要扩展。 - 如果的结构差异很大,合并后可能形成一棵新的结构不同的。 以上方法提供了不同结构的合并思路。实际应用中,需要根据具体需求选择合适的合并策略。 §§相关问题§§: 1. 如何合并两棵二叉搜索并保持平衡? 2. 如果两棵二叉结构不同,如何安全地合并它们? 3. 合并两棵时如何处理节点值以外的属性?</think>### 合并两棵的方法 以下是不同结构下的合并方法,根据的类型选择合适方案: --- #### **1. 二叉合并(节点值相加)** 适用于两棵结构相似的二叉,合并规则为对应节点值相加: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def mergeTrees(root1, root2): if not root1: return root2 if not root2: return root1 # 节点值相加 merged = TreeNode(root1.val + root2.val) # 递归合并左右子树 merged.left = mergeTrees(root1.left, root2.left) merged.right = mergeTrees(root1.right, root2.right) return merged ``` - **时间复杂度**:$O(\min(m,n))$($m,n$ 为两棵节点数) - **空间复杂度**:$O(\min(m,n))$(递归栈深度) --- #### **2. 二叉搜索(BST)合并** 通过中序遍历获取有序数组,再合并数组重建BST: ```python def inorder(root, arr): if root: inorder(root.left, arr) arr.append(root.val) inorder(root.right, arr) def mergeBSTs(root1, root2): arr1, arr2 = [], [] inorder(root1, arr1) inorder(root2, arr2) # 合并有序数组 merged_arr = [] i = j = 0 while i < len(arr1) and j < len(arr2): if arr1[i] < arr2[j]: merged_arr.append(arr1[i]) i += 1 else: merged_arr.append(arr2[j]) j += 1 merged_arr.extend(arr1[i:] or arr2[j:]) # 有序数组重建BST def build_bst(arr, l, r): if l > r: return None mid = (l + r) // 2 root = TreeNode(arr[mid]) root.left = build_bst(arr, l, mid-1) root.right = build_bst(arr, mid+1, r) return root return build_bst(merged_arr, 0, len(merged_arr)-1) ``` - **时间复杂度**:$O(m + n)$(遍历和数组合并) - **空间复杂度**:$O(m + n)$(存储中序序列) --- #### **3. 通用合并(子节点列表处理)** 适用于多子节点的结构(如N叉),合并相同层级的子节点: ```python class Node: def __init__(self, val=None, children=None): self.val = val self.children = children if children else [] def merge_trees(root1, root2): if not root1: return root2 if not root2: return root1 # 合并节点值(示例为相加) merged = Node(root1.val + root2.val) # 合并子节点列表 max_len = max(len(root1.children), len(root2.children)) for i in range(max_len): child1 = root1.children[i] if i < len(root1.children) else None child2 = root2.children[i] if i < len(root2.children) else None merged.children.append(merge_trees(child1, child2)) return merged ``` --- ### **关键注意事项** - **结构一致性**:二叉合并需结构相似,BST合并需保持有序性。 - **自定义合并规则**:上述示例为节点值相加,可替换为其他操作(如取最大值)。 - **空处理**:任一为空时直接返回另一棵树- **内存优化**:BST合并可优化为 $O(1)$ 额外空间(Morris遍历+链表合并)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值