该题为我们对二叉树遍历框架使用中明确【什么时候做】提供学习参考。
具体有关二叉树遍历框架可参考二叉树遍历框架
652. 寻找重复的子树
解法:递归+遍历框架
依旧是同样的求解思路,明确「该做什么」和「什么时候做」:
- 「该做什么」对于每个节点,需要描述以其为根节点的树内容。
- 「什么时候做」先得到左子树的描述,再得到右子树的描述,再加上根节点。因此是后序遍历。
在这里,对子树的描述可以采用二叉树的序列化表示,即利用二叉树的前序/中序/后序遍历结果来描述二叉树的结构。我们用非数字的特殊符#表示空指针,并且用字符,分隔每个二叉树节点值,这属于序列化二叉树的套路了。例如,对于上例中的:
我们可以表示为 ##4,#,2 (后序遍历)。
另外该题需要对重复结构进行判断,这需要我们借助一个数据结构来对已有结构进行存储,这里可以采用哈希表或者集合。但对于后者会出现出现次数>2的结构会被重复统计的情况,因此我们采用哈希表来存储。具体代码如下:
# 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 findDuplicateSubtrees(self, root: Optional[TreeNode]) -> List[Optional[TreeNode]]:
res = {}
result = []
def search(node):
if not node:
return "#"
left = search(node.left)
right = search(node.right)
# 采用","来分隔每个二叉树结构的节点描述值,
# 具体可通过将[10,2,22,1,12,1,1]作为输入示例,并打印中间结果来理解。
tree = left + "," + right + "," + str(node.val)
if tree in res:
if res[tree] == 1:
result.append(node)
res[tree] += 1
else:
res[tree] = 1
return tree
search(root)
return result
1365. 有多少数小于当前数字的数字
解法:计数排序
注意到数组元素的值域为 [0,100],所以可以考虑建立一个频次数组 cnt,cnt[i] 表示数字 i 出现的次数。那么对于数字 i 而言,小于它的数目就为 cnt[0…i-1] 的总和。cnt[0…i-1]的总和可以用前缀和来求解。
class Solution:
def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
cnt = [0] * 101
for num in nums:
cnt[num] += 1
for i in range(1, len(cnt)):
cnt[i] += cnt[i-1]
result = []
for num in nums:
# 需要注意边界值,对于=0,没有比其更小的数字
if num-1 < 0:
result.append(0)
else:
result.append(cnt[num-1])
return result