[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),每个节点都会被访问到一次;每个迭代中,有个i==layer_size-1判断,会增加时间消耗,考虑进行后续优化,遍历一层开始时,将这一层最右边的元素加入到结果中即可。

空间复杂度: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

 

 

 

posted @ 2021-04-13 11:30  gele00  阅读(65)  评论(0编辑  收藏  举报