[leetcode 199] 二叉树的右视图
题目:给定一棵二叉树,想想自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
分析:最容易想到是bfs,层次遍历二叉树,对于每一层,取出最后侧的节点即可。
稍微改写层次遍历的方法即可:
1.bfs,使用层次遍历的方法:
class Solution: def rightSideView(self, root: TreeNode) -> List[int]: # 迭代法,或递归法 # 1.如果是完全二叉树,每次访问节点后,再访问其右节点机可; # 2.对于一般的二叉树,看到的是每一层的最右边的节点。 # 考虑用层次访问二叉树的方法 res = [] if not root: return res from collections import deque layer_deque = deque([root]) while layer_deque: layer_size = len(layer_deque) for i in range(layer_size): node = layer_deque.popleft() left,right = node.left,node.right if left: layer_deque.append(left) if right: layer_deque.append(right) if i == layer_size - 1: res.append(node.val) return res
空间复杂度:O(N),layer_deque中最多可能保存N//2个节点数。
class Solution: def rightSideView(self, root: TreeNode) -> List[int]: # 迭代法,或递归法 # 1.如果是完全二叉树,每次访问节点后,再访问其右节点机可; # 2.对于一般的二叉树,看到的是每一层的最右边的节点。 # 考虑用层次访问二叉树的方法 res = [] if not root: return res from collections import deque layer_deque = deque([root]) while layer_deque: res.append(layer_deque[-1].val) layer_size = len(layer_deque) for _ in range(layer_size): node = layer_deque.popleft() left, right = node.left, node.right if left: layer_deque.append(left) if right: layer_deque.append(right) return res
2.是否可以采用dfs,递归的方式:
也可以采用递归法,获取左子树的res,获取右子树的情况,合并左右子树,拼接到原来的。
class Solution: def rightSideView(self, root: TreeNode) -> List[int]: # 迭代法,或递归法 # 1.如果是完全二叉树,每次访问节点后,再访问其右节点机可; # 2.对于一般的二叉树,看到的是每一层的最右边的节点。 # 考虑用层次访问二叉树的方法 def dfs(node): if not node: return [] res = [node.val] left_res = dfs(node.left) right_res = dfs(node.right) if len(left_res) > len(right_res): res = res + right_res + left_res[len(right_res):] else: res = res + right_res return res return dfs(root)
时间复杂度:O(N),每个节点也都会被访问到。并且,存在对结果list的拼接,会导致一些数组的新建等现象。
空间复杂度:O(N),递归调用层数等于二叉树的深度depth,同时也需要临时的list,存储每个子节点的情况。
考虑第二种形式:
class Solution: def rightSideView(self, root: TreeNode) -> List[int]: # 迭代法,或递归法 # 1.如果是完全二叉树,每次访问节点后,再访问其右节点机可; # 2.对于一般的二叉树,看到的是每一层的最右边的节点。 # 考虑用层次访问二叉树的方法 def dfs(node,res): if not node: return res res.append(node.val) left_res = dfs(node.left,res.copy()) right_res = dfs(node.right,res.copy()) return right_res + left_res[len(right_res):] return dfs(root,[])
时间复杂度:O(N)
空间复杂度:O(N),除了递归栈空间,还需额外O(N)空间存储res.
再一种写法:减少临时空间
class Solution: def rightSideView(self, root: TreeNode) -> List[int]: # 迭代法,或递归法 # 1.如果是完全二叉树,每次访问节点后,再访问其右节点机可; # 2.对于一般的二叉树,看到的是每一层的最右边的节点。 # 考虑用层次访问二叉树的方法 res = [] def dfs(node,depth): if not node: return res if len(res)==depth: res.append(node.val) dfs(node.right,depth+1) dfs(node.left,depth+1) dfs(root,0) return res
最后,使用迭代方式实现dfs
class Solution: def rightSideView(self, root: TreeNode) -> List[int]: # 迭代法,或递归法 # 1.如果是完全二叉树,每次访问节点后,再访问其右节点机可; # 2.对于一般的二叉树,看到的是每一层的最右边的节点。 # 考虑用层次访问二叉树的方法 res = [] if not root: return res stack = [(root,0)] while stack: node,depth = stack.pop() if depth == len(res): res.append(node.val) if node.left: stack.append((node.left,depth+1)) if node.right: stack.append((node.right,depth+1)) return res