牛客网在线编程专题《剑指offer-面试题23》从上往下打印二叉树

我的个人微信公众号:Microstrong

微信公众号ID:MicrostrongAI

公众号介绍:Microstrong(小强)同学主要研究机器学习、深度学习、计算机视觉、智能对话系统相关内容,分享在学习过程中的读书笔记!期待您的关注,欢迎一起学习交流进步!

个人博客:https://blog.csdn.net/program_developer

知乎专栏:https://zhuanlan.zhihu.com/Microstrong

微信公众号

题目链接:

 https://www.nowcoder.com/practice/7fe2212963db4790b57431d9ed259701?tpId=13&tqId=11175&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述:

解题思路:

       这道题实质是考查树的遍历算法, 只是这种遍历不是我们熟悉的前序、中序或者后序遍历。 由于我们不太熟悉这种按层遍历的方法, 可能一下子也想不清楚遍历的过程。 那面试的时候怎么办呢?我们不妨先分析一下打印图1中的二叉树的过程。

        因为按层打印的顺序决定应该先打印根节点, 所以我们从树的根节点开始分析。 为了接下来能够打印值为8的节点的两个子节点, 我们应该在遍历到该节点时把值为6和10的两个节点保存到一个容器里,现在容器内就有两个节点了。按照从左到右打印的要求,我们先取出值为6的节点。打印出值6之后,把它的值分别为5和7的两个节点放入数据容器。此时数据容器中有3个节点,值分别为10、5和7。接下来我们从数据容器中取出值为10的节点。注意到值为10的节点比值为5和7的节点先放入容器,此时又比这两个节点先取出,这就是我们通常所说的先入先出,因此不难看出这个数据容器应该是一个队列。由于值为5、7、9、11的节点都没有子节点, 因此只要依次打印即可。 整个打印过程如表1所示。

图1:一颗二叉树,从上往下按层打印的顺序为8、6、10、5、7、9、11
表1 按层打印图1中二叉树的过程
步骤操作队列
1打印结点8结点6、结点10
2打印结点6结点10、结点5、结点7
3打印结点10结点5、结点7、结点9、结点11
4打印结点5结点7、结点9、结点11
5打印结点7结点9、结点11
6打印结点9结点11
7打印结点11 

        通过上面具体例子的分析, 我们可以找到从上到下打印二叉树的规律:每次打印一个节点的时候, 如果该节点有子节点, 则把该节点的子节点放到一个队列的末尾。 接下来到队列的头部取出最早进入队列的节点, 重复前面的打印操作, 直至队列中所有的节点都被打印出来。

       既然我们已经确定数据容器是一个队列了,现在的问题就是如何实现一个队列。这里我们借助Python的列表(list)实现队列。

已经AC的代码:


class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution:

    def PrintFromTopToBottom(self, root):
        # 当节点非空时才进行操作
        if not root:
            return []

        if root != None:
            # 用于存放还未遍历的元素
            list = []
            # 用于存放最终的结果
            result = []
            # 将根节点入队
            list.append(root)
            # 队列非空则进行处理
            while list:
                # 删除队首元素
                curNode = list.pop(0)
                # 输出队首元素的值
                result.append(curNode.val)
                # 如果左子结点不为空,则左子节点入队
                if curNode.left != None:
                    list.append(curNode.left)
                # 如果右子节点不为空,则右子节点入队
                if curNode.right != None:
                    list.append(curNode.right)
        return result

if __name__ == "__main__":

#----------------------测试用例1-------------------------------------------------
#            8
#          / \
#        6    10
#      /  \   / \
#    5   7   9  11

    # root = TreeNode(8)
    #
    # root.left = TreeNode(6)
    #
    # root.right = TreeNode(10)
    #
    # root.left.left = TreeNode(5)
    #
    # root.left.right = TreeNode(7)
    #
    # root.right.left = TreeNode(9)
    #
    # root.right.right = TreeNode(11)

#----------------------测试用例2-------------------------------------------------
#                1
#              /
#            3
#          /
#        5
#      /
#     7
#    /
#  9

    # root = TreeNode(1)
    #
    # root.left = TreeNode(3)
    #
    # root.left.left = TreeNode(5)
    #
    # root.left.left.left = TreeNode(7)
    #
    # root.left.left.left.left = TreeNode(9)

#----------------------测试用例3-------------------------------------------------
#            0
#            \
#             2
#              \
#               4
#                \
#                 8

    root = TreeNode(0)

    root.right = TreeNode(2)

    root.right.right = TreeNode(4)

    root.right.right.right = TreeNode(6)

    root.right.right.right.right = TreeNode(8)

    sol = Solution()
    print(sol.PrintFromTopToBottom(root))

Reference:

【1】《剑指offer》,何海涛著。
【2】 https://wiki.jikexueyuan.com/project/for-offer/question-twenty-three.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值