Loading。。。


算法题记录 34

199.二叉树的右视图(中等)

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

涉及知识点

二叉树

解决思路

先递归右边再左边,通过深度来判定入不入列表即可。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
ans = []
def dfs(node: Optional[TreeNode], depth: int) -> None:
if node is None:
return
if depth == len(ans): # 这个深度首次遇到
ans.append(node.val)
dfs(node.right, depth + 1) # 先递归右子树,保证首次遇到的一定是最右边的节点
dfs(node.left, depth + 1)
dfs(root, 0)
return ans

114.二叉树展开为链表(中等)

给你二叉树的根结点 root ,请你将它展开为一个单链表:

展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。

涉及知识点

二叉树

解决思路

发现递归顺序就很好做,右子树左子树根。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
head = None

def flatten(self, root: Optional[TreeNode]) -> None:
if root is None:
return
self.flatten(root.right)
self.flatten(root.left)
root.left = None
root.right = self.head # 头插法,相当于链表的 root.next = head
self.head = root # 现在链表头节点是 root

105.从前序与中序遍历序列构造二叉树(中等)

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

涉及知识点

二叉树

解决思路

最基本的二叉树性质。

1
2
3
4
5
6
7
8
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if not preorder: # 空节点
return None
left_size = inorder.index(preorder[0]) # 左子树的大小
left = self.buildTree(preorder[1: 1 + left_size], inorder[:left_size])
right = self.buildTree(preorder[1 + left_size:], inorder[1 + left_size:])
return TreeNode(preorder[0], left, right)

437.路径总和3(中等)

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。

路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

涉及知识点

二叉树

解决思路

跟前面一题很像,前缀和+哈希表,从根节点开始用树的方式左右遍历更新前缀和、哈希表,cnt[s−targetSum]得到满足要求的数量即可。因为要求连续且向下,本质上就是求和为K的子数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> int:
ans = 0
cnt = defaultdict(int)
cnt[0] = 1

def dfs(node: Optional[TreeNode], s: int) -> None:
if node is None:
return
nonlocal ans
s += node.val
ans += cnt[s - targetSum]
cnt[s] += 1
dfs(node.left, s)
dfs(node.right, s)
cnt[s] -= 1 # 恢复现场

dfs(root, 0)
return ans

236.二叉树的最近公共祖先(中等)

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

涉及知识点

二叉树

解决思路

还是正常的递归,如果左右都找到了,那当前的节点就是目标节点,如果当前节点为p、q,那就没往下讨论的必要了,直接返回当前节点即可。注意最后返回的是left or right即可,比较巧妙。

1
2
3
4
5
6
7
8
9
class Solution:
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
if root in (None, p, q):
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if left and right: # 左右都找到
return root # 当前节点是最近公共祖先
return left or right

124.二叉树中的最大路径和(中等)

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

涉及知识点

二叉树

解决思路

没啥好说的,就普通递归。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def maxPathSum(self, root: Optional[TreeNode]) -> int:
ans = -inf
def dfs(node: Optional[TreeNode]) -> int:
if node is None:
return 0 # 没有节点,和为 0
l_val = dfs(node.left) # 左子树最大链和
r_val = dfs(node.right) # 右子树最大链和
nonlocal ans
ans = max(ans, l_val + r_val + node.val) # 两条链拼成路径
return max(max(l_val, r_val) + node.val, 0) # 当前子树最大链和(注意这里和 0 取最大值了)
dfs(root)
return ans

声明

题目均来源于leetcode公开题库,部分方法解析来源于高赞题解,如有不妥请联系。


文章作者: codeYu233
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 codeYu233 !
评论
  目录