python算法之利用广度优先遍历解决二叉树的右侧问题

二叉树的右侧

问题:

小明和小伙伴去摘柠檬,小明负责摘树的右侧的柠檬,假如柠檬树的每个树干只有两个树枝、一个树枝、零个树枝三种可能,那么一棵树可以被看作一颗二叉树,小明摘树的右侧,让我们算一下,它可以摘到哪些柠檬。

解决问题

这个问题可以用二叉树来表示,如图:
树1:
在这里插入图片描述
树2:
在这里插入图片描述

对于树1来说,小明可以摘到的柠檬为1、3、6、7这四个柠檬。
对于树2来说,小明可以摘到的柠檬为1、3、5、7,也就是说要摘下站在树右边能看到的柠檬。

注意:二叉树是每个节点最多有两个子树的树结构

此时,本题的问题就变成了给定一颗二叉树,想想你自己站在该二叉树的右侧,按照从根节点到低端叶子节点的顺序,找出可以获取的节点的值的问题。

为了表示这样的树,需要定义一个二叉树的结构 ,代码如下:

class TreeNode(object):#定义二叉树的根节点为TreenNode
    def __init__(self,x):
        self.val = x  #定义二叉树的每个元素的值,这里表示柠檬的编号
        self.left = None  #定义二叉树的每个元素的左子树
        self.right = None   #定义二叉树的每个元素的右子树

根据前面的分析,为了找出二叉树右侧的节点的值,我们需要一层一层地取出每一层的数据,然后把每层的数据放入最终结果中。我们为每个节点设定一个层级,比如根节点的层级是第1层,根节点的子节点的层级是第2层,依次递增。

二叉树的层次结构:
在这里插入图片描述
,这个题目是遍历问题,或者说是求二叉树广度优先遍历的一种变形,我们只需要薄层每一层最右边的数字即可。
因为是广度优先遍历算法,一定要用到队列,使用队列来保存待处理的节点。首先处理根节点,存储根节点的值,同时建立存放结果的列表,代码框架如下:

def rightSide(root):
    result = []   #存放结果数据
    queue = [root]    #队列存放待处理数据
    while len(queue) > 0:
           #队列不为空时,以此取出数据做处理
    return result

使用广度优先遍历算法的时候,需要先取出每层的节点,然后处理该节点,之后把下一次的左右节点都存放入队列,以此类推,到队列为空,处理就完毕了。

核心问题就是如何找到每层的最后一个节点,我们可以在处理每层数据的是时候记录一下当前层的节点数N,那么本层最后一个节点就是当前队列里的第N个数据,在寻找每层最后一个元素的同时,把每个节点的左右节点加入队列,一直到这一层的所有元素都分析完为止。对于每层节点的分析,使用一个for循环来处理。整个程序在队列为空时结束:

 while len(queue) > 0:   #队列不为空时,依次取出数据做处理
        length = len(queue)   #先保存本层的数量
        for i in range(length):   #以此处理每一行
            node = queue.pop()   #取出队列头的点
            if i == length - 1:   #当该点时最后一个点的时候把他加入结果数组里
                result.append(node.val)
            if node.left != None:
                queue.append(node.left)#  把左节点加入队列
            if node.right != None:
                queue.append(node.right)  #把右节点加入队列

注意:数组下标从0开始,所以代码中每层最后一个元素是N-1

通过广度优先遍历就可以自顶向下找到这些具有下划线的节点,每条线上的数字代表访问他们的顺序,如图:
在这里插入图片描述

最终代码:

class TreeNode(object):#定义二叉树的根节点为TreenNode
    def __init__(self,x):
        self.val = x  #定义二叉树的每个元素的值,这里表示柠檬的编号
        self.left = None  #定义二叉树的每个元素的左子树
        self.right = None   #定义二叉树的每个元素的右子树
def rightSide(root):
    result = []#存放结果数据
    queue = [root]#先队列存放待处理数据
    while len(queue) > 0:#  队列长度不为空则继续循环
        length = len(queue)#获取队列长度
        for i in range(length):#以此处理每一行
            node = queue.pop() #取出队列头的点
            if i == length - 1: #当该点时最后一个点的时候把他加入结果数组里
                result.append(node.val)
            if node.left != None:
                queue.append(node.left)#把左节点加入队列
            if node.right != None:
                queue.append(node.right)#把右节点加入队列
    return result
node1 = TreeNode(1)  #以下为测试代码
node2 = TreeNode(2)
node3 = TreeNode(3)
node1.right = node2
node2.right = node3
print(rightSide(node1))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黎明之道

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

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

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

打赏作者

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

抵扣说明:

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

余额充值