257、二叉树的所有路径
给你一个二叉树的根节点 root
,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例1:
输入:root = [1,2,3,null,5]
输出:["1->2->5","1->3"]
示例2:
输入:root = [1]
输出:["1"]
思路:
递归拼接所有路径
class Solution:
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
if not root: return []
# 如果没有子节点,返回结点字符串的数组
if not root.left and not root.right:
return [str(root.val)]
left = self.binaryTreePaths(root.left)
right = self.binaryTreePaths(root.right)
ans = left + right
# 进行左右子树路径字符串的拼接
return [f"{root.val}->{item}" for item in ans]
404、左叶子之和
给定二叉树的根节点 root
,返回所有左叶子之和。
示例1:
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例2:
输入: root = [1]
输出: 0
思路:
深度优先遍历,在遍历左子节点的过程中,判断是否是叶子结点,如果是则累计加和
class Solution:
def sumOfLeftLeaves(self, root: TreeNode) -> int:
if not root: return 0
stack = []
cur = root
ans = 0
while cur or stack:
while cur:
stack.append(cur)
cur = cur.left
# 如果当前结点是叶子节点,说明该叶子节点是满足条件的左叶子节点,累加和即可
if cur and not cur.left and not cur.right::
ans += cur.val
cur = stack.pop()
cur = cur.right
return ans
671、二叉树中第二小的节点
给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个。
更正式地说,即 root.val = min(root.left.val, root.right.val) 总成立。
给出这样的一个二叉树,你需要输出所有节点中的 第二小的值 。
如果第二小的值不存在的话,输出 -1 。
示例1:
输入:root = [2,2,5,null,null,5,7]
输出:5
解释:最小的值是 2 ,第二小的值是 5 。
示例2:
输入:root = [2,2,2]
输出:-1
解释:最小的值是 2, 但是不存在第二小的值。
思路:
由于节点值等于左右子节点中较小的一个,那么可以得出结论,根节点是整棵树中最小的节点,那么第二小的节点是严格大于根节点值的节点,可以递归遍历,找到比根节点大的值。
class Solution:
def findSecondMinimumValue(self, root: TreeNode) -> int:
self.ans, root_val = -1, root.val
def dfs(root):
if not root: return
# 如果ans有值,并且结点值大于ans的值,说明该子树的所有值都大于等于ans,提前跳出即可
if self.ans != -1 and root.val >= self.ans:
return
# 如果结点值大于根节点的值,更新ans的值
if root.val > root_val:
ans = root.val
dfs(root.left)
dfs(root.right)
dfs(root)
return self.ans
993、二叉树的堂兄弟节点
在二叉树中,根节点位于深度 0 处,每个深度为 k 的节点的子节点位于深度 k+1 处。
如果二叉树的两个节点深度相同,但 父节点不同 ,则它们是一对堂兄弟节点。
我们给出了具有唯一值的二叉树的根节点 root ,以及树中两个不同节点的值 x 和 y 。
只有与值 x 和 y 对应的节点是堂兄弟节点时,才返回 true 。否则,返回 false。
示例1:
输入:root = [1,2,3,4], x = 4, y = 3
输出:false
示例2:
输入:root = [1,2,3,null,4,null,5], x = 5, y = 4
输出:true
示例3:
输入:root = [1,2,3,null,4], x = 2, y = 3
输出:false
思路:
满足堂兄弟节点的条件为,两个结点在同一层,两个结点的父节点不一样。
这样考虑下来,就很自然的想到使用层序遍历,由于二叉树是具有唯一值的,也就是不会出现两个同样值的结点。找到子节点之后,如果发现父节点不一致,那么直接返回即可
class Solution:
def isCousins(self, root: TreeNode, x: int, y: int) -> bool:
queue = [root]
while queue:
n = len(queue)
parent = None
# 层序遍历
for i in range(n):
cur = queue.pop(0)
# 遍历每个节点左右子节点,找到指定的结点
for node in [cur.left, cur.right]:
if not node: continue
queue.append(node)
if node.val != x and node.val != y: continue
# 如果找到结点,判断父节点是否存在,如果存在说明之前已经找到一个结点,
# 那么判断一下父节点和当前结点的父节点是否一致,这里直接返回即可,因为二叉树是具有唯一值的
# 否则给父节点赋值
if parent: return cur != parent
else: parent = cur
return False
1022、从根到叶的二进制之和
给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。
对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。
返回这些数字之和。题目数据保证答案是一个 32 位 整数。
示例1:
输入:root = [1,0,1,0,1,0,1]
输出:22
解释:(100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22
示例2:
输入:root = [0]
输出:0
示例3:
输入:root = [1]
输出:1
示例4:
输入:root = [1,1]
输出:3
思路:
先递归找到所有从根到叶的路径并拼接成二进制,然后转化为10进制进行求和
class Solution:
def sumRootToLeaf(self, root: Optional[TreeNode]) -> int:
def dfs(root):
if not root: return []
if not root.left and not root.right: return [str(root.val)]
left = dfs(root.left)
right = dfs(root.right)
ans = left + right
# 进行路径拼接
return [f"{root.val}{val}"for val in ans]
ans = dfs(root)
# int第二个参数是当前传入的数据是以什么进制传入的,这里传2指的是以二进制传入
return sum([int(item, 2) for item in ans])