100. 相同的树
给定两个二叉树,编写一个函数来检验它们是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例 1:
输入:
1 1
/ \ / \
2 3 2 3
[1,2,3], [1,2,3]
输出: true
示例 2:
输入:
1 1
/ \
2 2
[1,2], [1,null,2]
输出: false
示例 3:
输入:
1 1
/ \ / \
2 1 1 2
[1,2,1], [1,1,2]
输出: false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/same-tree
普通写法1:深度优先搜索(7行)
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
if not p and not q:
return True
if not p or not q:
return False
if p.val != q.val:
return False
return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
思路:判断当下节点是否相同,而后判断左孩子和右孩子是否相同。如果p
和q
都是null
则当下相同;p
和q
有一个是null
则不同;否则看二者value
是否相同。
普通写法2:广度优先搜索(17行)
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
def check(p, q):
if not p and not q:
return True
if not q or not p:
return False
if p.val != q.val:
return False
return True
deq = deque([(p, q)])
while deq:
p, q = deq.popleft()
if not check(p, q):
return False
if p:
deq.append((p.left, q.left))
deq.append((p.right, q.right))
return True
思路:用一个双边队列将当下节点的孩子放在队列里,每次都查看当前队首是否相同。
大神写法1:深度优先搜索(3行)
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
if p and q:
return p.val == q.val and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
return p is q
思路与普通写法1一致。return p is q
等价于return True if p == None and q == None else False
。
大神写法2:广度优先搜索(3行)
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
def t(n):
return n and (n.val, t(n.left), t(n.right))
return t(p) == t(q)
将所有的节点展成元组的形式,(root, left, right)
。由于and
只在前项为真时返回后项的逻辑值,所以遇到空节点会返回空。
举例,如果二叉树p
的形状是:
1
/ \
2 3
/
4
print(t(p))
返回
(1, (2, (4, None, None), None), (3, None, None))
这里的(n.val, t(n.left), t(n.right))
换成[n.val, t(n.left), t(n.right)]
也可以。
上帝之手(1行)
def isSameTree(self, p, q):
return p and q and p.val == q.val and all(map(self.isSameTree, (p.left, p.right), (q.left, q.right))) or p is q
思路与深度优先搜索一致。
上述所有写法的时间复杂度(除大神写法2)都是O(min(m,n))
其中m,n
表示两棵树的叶子节点数。如果先遍历两棵树再比较,也包括大神写法2,复杂度是O(max(m,n))
。