摘要:文章目錄題目示例說明限制解法一分析實現復雜度題目給定一棵二叉樹的根節點,請返回所有的重復子樹。示例示例輸入輸出示例輸入輸出示例輸入輸出說明來源力扣鏈接限制二叉樹中的節點數量在之間。
給定一棵二叉樹的根節點,請返回所有的重復子樹。對于每一類重復子樹,你只需要返回其中任意一個的根節點即可。如果兩棵二叉樹擁有相同的結構和節點值,則稱這兩棵二叉樹是重復的。
示例 1 1 1 :
- 輸入:
root = [1, 2, 3, 4, null, 2, 4, null, null, 4]
- 輸出:
[[2, 4], [4]]
示例 2 2 2 :
- 輸入:
root = [2, 1, 1]
- 輸出:
[[1]]
示例 3 3 3 :
- 輸入:
root = [2, 2, 2, 3, null, 3, null]
- 輸出:
[[2, 3], [3]]
- 來源: 力扣(LeetCode)
- 鏈接: https://leetcode-cn.com/problems/find-duplicate-subtrees
- 二叉樹中的節點數量在 [ 1 , ? 1 0 4 ] [1,/textit{ }10^4] [1,?104] 之間;
-200 <= Node.val <= 200
。
想要正確解答本題,只需要知道如何給出二叉樹的某種唯一性表達即可,接下來首先獲得以給定二叉樹的所有節點為根節點的子二叉樹的表達形式,然后得到所有重復表達形式對應子樹的根節點即可。
實際上,所謂給出二叉樹的某種唯一表達其實就是對二叉樹進行序列化,而在【LeetCode 二叉樹專項】二叉樹的序列化與反序列化(297)中,我們給出了基于二叉樹深度優先搜索(前序遍歷、后序遍歷)以及廣度優先搜索實現的二叉樹序列化。
接下來,需要確定就是具體采用哪種方式序列化。本題采用二叉樹的后序遍歷對給定二叉樹的所有子樹進行序列化。
from json import dumpsfrom typing import Optional, List, Set, Dict, Unionclass TreeNode: def __init__(self, val=0, left: "TreeNode" = None, right: "TreeNode" = None): self.val = val self.left = left self.right = rightclass Solution: def _find_duplicate_subtrees(self, root: TreeNode, memorandum: Dict[str, int], results: List[TreeNode]) -> Optional[List[int]]: if not isinstance(root, TreeNode): return left = self._find_duplicate_subtrees(root.left, memorandum, results) right = self._find_duplicate_subtrees(root.right, memorandum, results) postorder = [] if left: postorder = postorder + left else: postorder.append(left) if right: postorder = postorder + right else: postorder.append(right) postorder.append(root.val) dumped = dumps(postorder) # if dumped in memorandum.keys() and memorandum[dumped] == 1: if memorandum.get(dumped, 0) == 1: # The above commented if-clause is a pedantic counterpart. results.append(root) memorandum[dumped] = memorandum.get(dumped, 0) + 1 return postorder def find_duplicate_subtrees(self, root: Optional[TreeNode]) -> Optional[List[TreeNode]]: if not isinstance(root, TreeNode): return memorandum = dict() results = [] self._find_duplicate_subtrees(root, memorandum, results) print("memorandum =", memorandum) return resultsdef postorder(root: TreeNode, tree: List[Union[int, None]]): if not root: tree.append(None) return postorder(root.left, tree) postorder(root.right, tree) tree.append(root.val)def main(): node7 = TreeNode(4) node6 = TreeNode(4) node5 = TreeNode(2, left=node7) node4 = TreeNode(4) node3 = TreeNode(3, node5, node6) node2 = TreeNode(2, left=node4) node1 = TreeNode(1, node2, node3) root = node1 sln = Solution() for root in sln.find_duplicate_subtrees(root): tree = [] postorder(root, tree) print("postorder =", dumps(tree))if __name__ == "__main__": main()
運行上述解答的輸出結果為:
memorandum = {"[null, null, 4]": 3, "[null, null, 4, null, 2]": 2, "[null, null, 4, null, 2, null, null, 4, 3]": 1, "[null, null, 4, null, 2, null, null, 4, null, 2, null, null, 4, 3, 1]": 1}postorder = [null, null, 4]postorder = [null, null, 4, null, 2]
實際上, LeetCode 官方通過使用 collections
模塊中的 Counter
類,給出了一個如下的非常優雅的解答,其中關于 Counter 類的使用,可以參考【源碼共讀】Python 標準模塊 collections 中 Counter 類詳解。
from typing import Optional, List, Dict, Unionfrom collections import Counterclass TreeNode: def __init__(self, val=0, left: "TreeNode" = None, right: "TreeNode" = None): self.val = val self.left = left self.right = rightclass Solution: def _collect(self, node: TreeNode, duplicates: List[TreeNode], count: Counter): if not node: return "#" serial = "{},{},{}".format(self._collect(node.left, duplicates, count), self._collect(node.right, duplicates, count), node.val) count[serial] += 1 if count[serial] == 2: duplicates.append(node) return serial def elegantly_find_duplicate_subtrees(self, root: Optional[TreeNode]) -> List[Optional[TreeNode]]: count = Counter() duplicates = [] self._collect(root, duplicates, count) return duplicatesdef postorder(root: TreeNode, tree: List[Union[int, None]]): if not root: tree.append(None) return postorder(root.left, tree) postorder(root.right, tree) tree.append(root.val)def main(): node7 = TreeNode(4) node6 = TreeNode(4) node5 = TreeNode(2, left=node7) node4 = TreeNode(4) node3 = TreeNode(3, node5, node6) node2 = TreeNode(2, left=node4) node1 = TreeNode(1, node2, node3) root = node1 sln = Solution() for root in sln.elegantly_find_duplicate_subtrees(root): tree = [] postorder(root, tree) print("postorder =", dumps(tree))if __name__ == "__main__": main()
實際上,在上述解答的 第 15 15 15 行中,如果將 return "#"
改為 return
也是正確的,但不為何此時在 LeetCode
上提交時,執行耗時和內存消耗的數據都非常差,希望看到這篇題解而且知道緣由的有緣人可以在評論區留下你的指導。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/123340.html
摘要:對于同一類的重復子樹,你只需要返回其中任意一棵的根結點即可。兩棵樹重復是指它們具有相同的結構以及相同的結點值。這里再用存儲,鍵序列化結果,值樹節點組成的鏈表。 題目地址:https://leetcode-cn.com/probl...題目描述:給定一棵二叉樹,返回所有重復的子樹。對于同一類的重復子樹,你只需要返回其中任意一棵的根結點即可。 兩棵樹重復是指它們具有相同的結構以及相同的結點...
摘要:解法一中序遍歷分析由于給定了二叉搜索樹,因此首先考慮中序遍歷,使用示例,我們先來分別看一下二叉搜索樹和累加樹中序遍歷的結果二叉搜索樹二叉累加樹。這里還是使用示例,我們再來觀察一下二叉搜索樹和累加樹中序遍歷的結果二叉搜索樹二叉累加樹。 ...
文章目錄 一、題目1、題目描述2、基礎框架3、原題鏈接 二、解題報告1、思路分析2、時間復雜度3、代碼詳解 三、本題小知識四、加群須知 一、題目 1、題目描述 ??給你一棵二叉搜索樹,請按 中序遍歷 將其重新排列為一棵遞增順序搜索樹,使樹中最左邊的節點成為樹的根節點,并且每個節點沒有左子節點,只有一個右子節點。??樣例輸入: [5,3,6,2,4,null,8,1,null,null,nu...
摘要:如果左右子樹返回的最低共同父節點值都不是空,說明和分別位于的左右子樹,那么就是最低共同父節點。 235題-題目要求 Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. According to the definition of L...
閱讀 2447·2021-11-15 11:38
閱讀 2831·2021-11-02 14:44
閱讀 3812·2021-09-26 10:13
閱讀 3054·2021-08-13 15:02
閱讀 776·2019-08-30 15:56
閱讀 1426·2019-08-30 15:53
閱讀 2357·2019-08-30 13:01
閱讀 3183·2019-08-29 12:57