Python算法题集_二叉树的右视图

本文介绍了如何使用Python解决二叉树的右视图问题,通过深度优先搜索(DFS)和广度优先搜索(BFS)两种方法实现,并提供了优化版本,以减少空间复杂度。最后对比了三种方法的运行时间和内存使用情况。
摘要由CSDN通过智能技术生成

本文为Python算法题集之一的代码示例

题199:二叉树的右视图

1. 示例说明

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

    示例 1:

    在这里插入图片描述

    输入: [1,2,3,null,5,null,4]
    输出: [1,3,4]
    

    示例 2:

    输入: [1,null,3]
    输出: [1,3]
    

    示例 3:

    输入: []
    输出: []
    

    提示:

    • 二叉树的节点个数的范围是 [0,100]
    • -100 <= Node.val <= 100

2. 题目解析

- 题意分解

  1. 本题为从右侧观察二叉树,输出每层最右边节点
  2. 基本的设计思路是深度优先算法【DFS(Depth-First Search)】、广度有限算法【BFS(Breadth-First Search)】

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集

  3. 通常优化:采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1. 可以考虑使用DFS、BFS进行层级遍历,得到最层右侧节点,所以本题本质上是二叉树的层级遍历题

    2. 可以在执行层级遍历时不生成遍历结果,仅保存最右边节点,空间复杂度简化为0(1)


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题本地化超时测试用例自己生成,详见【最优算法章节】

3. 代码展开

1) 标准求解【DFS递归】

使用深度优先算法,在递归中传入层级参数

性能良好,超过85%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 def rightSideView_base(self, root):
     if not root:
         return []
     result = []
     def dfsTraversal(ilevel, root):
         if len(result) < ilevel:
             result.append([])
         result[ilevel - 1] = root.val
         if root.left:
             dfsTraversal(ilevel + 1, root.left)
         if root.right:
             dfsTraversal(ilevel + 1, root.right)
     dfsTraversal(1, root)
     return result

aroot = generate_binary_tree(ilen, imode)
aSolution = Solution()
result = cfp.getTimeMemoryStr(Solution.rightSideView_base, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result'][1:5]))

# 运行结果
函数 rightSideView_base 的运行时间为 518.61 ms;内存使用量为 8.00 KB 执行结果 = [10, 72, 8, 49]

2) 改进版一【BFS迭代】

使用列表结构【list】作为堆栈,后进先出实现BFS遍历

马马虎虎,超过70%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 def rightSideView_ext1(self, root):
     if not root:
         return []
     result = []
     stack_tree = [(root, 1)]
     while stack_tree:
         node, depth = stack_tree.pop()
         if len(result) < depth:
             result.append([])
         result[depth - 1] = node.val
         if node.right: stack_tree.append((node.right, depth + 1))
         if node.left: stack_tree.append((node.left, depth + 1))
     return result

aroot = generate_binary_tree(ilen, imode)
aSolution = Solution()
result = cfp.getTimeMemoryStr(Solution.rightSideView_ext1, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result'][1:5]))

# 运行结果
函数 rightSideView_ext1 的运行时间为 756.01 ms;内存使用量为 0.00 KB 执行结果 = [10, 72, 8, 49]

3) 改进版二【BFS迭代+块循环】

使用高速双向队列结构【deque】作为队列,先进先出实现BFS遍历,填充每层节点

性能良好,超过83%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 def rightSideView_ext2(self, root):
     from collections import deque
     if not root:
         return []
     result = []
     queue_tree = deque([root])
     while queue_tree:
         ilen = len(queue_tree)
         tmp = []
         for iIdx in range(ilen):
             tmproot = queue_tree.popleft()
             tmp.append(tmproot.val)
             if tmproot.left:
                 queue_tree.append(tmproot.left)
             if tmproot.right:
                 queue_tree.append(tmproot.right)
         result.append(tmp[-1])
     return result

aroot = generate_binary_tree(ilen, imode)
aSolution = Solution()
result = cfp.getTimeMemoryStr(Solution.rightSideView_ext2, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result'][1:5]))

# 运行结果
函数 rightSideView_ext2 的运行时间为 1020.27 ms;内存使用量为 1344.00 KB 执行结果 = [10, 72, 8, 49]

4. 最优算法

根据本地日志分析,最优算法为第1种方式【DFS递归】rightSideView_base

import random
ilen, imode = 4000000, 1
def generate_binary_tree(node_count, imode):
    if node_count <= 0:
        return None
    root = TreeNode(random.randint(1, 100))
    node_count -= 1
    if imode > 3:
        imode = 1
    if imode == 1:
        left = generate_binary_tree(node_count // 2, imode+1)
        right = generate_binary_tree(node_count // 2, imode+1)
        root.left = left
        root.right = right
    elif imode==2:
        left = generate_binary_tree(node_count, imode+1)
        root.left = left
    else:
        right = generate_binary_tree(node_count, imode+1)
        root.right = right
    return root
aroot = generate_binary_tree(ilen, imode)
aSolution = Solution()
result = cfp.getTimeMemoryStr(Solution.rightSideView_base, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result'][1:5]))
result = cfp.getTimeMemoryStr(Solution.rightSideView_ext1, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result'][1:5]))
result = cfp.getTimeMemoryStr(Solution.rightSideView_ext2, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result'][1:5]))

# 算法本地速度实测比较
函数 rightSideView_base 的运行时间为 518.61 ms;内存使用量为 8.00 KB 执行结果 = [10, 72, 8, 49]
函数 rightSideView_ext1 的运行时间为 756.01 ms;内存使用量为 0.00 KB 执行结果 = [10, 72, 8, 49]
函数 rightSideView_ext2 的运行时间为 1020.27 ms;内存使用量为 1344.00 KB 执行结果 = [10, 72, 8, 49]

一日练,一日功,一日不练十日空

may the odds be ever in your favor ~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长孤秋落

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值