Python算法题集_二叉树的右视图
本文为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. 题目解析
- 题意分解
- 本题为从右侧观察二叉树,输出每层最右边节点
- 基本的设计思路是深度优先算法【DFS(Depth-First Search)】、广度有限算法【BFS(Breadth-First Search)】
- 优化思路
-
通常优化:减少循环层次
-
通常优化:增加分支,减少计算集
-
通常优化:采用内置算法来提升计算速度
-
分析题目特点,分析最优解
-
可以考虑使用DFS、BFS进行层级遍历,得到最层右侧节点,所以本题本质上是二叉树的层级遍历题
-
可以在执行层级遍历时不生成遍历结果,仅保存最右边节点,空间复杂度简化为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 ~