二叉树层序遍历递归与非递归_LeetCode0102: 二叉树的层序遍历

题目介绍

描述:给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例:
二叉树:[3,9,20,null,null,15,7],

    3
   / 
  9  20
    /  
   15   7
返回其层次遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

解题思路

递归算法的关键是要明确函数的「定义」是什么,然后相信这个定义,利用这个定义推导最终结果。
写树相关的算法,简单说就是,先搞清楚当前 root 节点该做什么,然后根据函数定义递归调用子节点,递归调用会让孩子节点做相同的事情。
二叉树题目的一个难点在于如何通过题目的要求思考出每一个节点需要做什么

如果根节点为空,则返回空列表,如果只有一个根节点,则返回只有根节点值的列表,然后根据宽度优先来依次遍历每一层。可以递归或者迭代

自己的解法实现

def levelOrder(self, root):
        if not root: return []
        stack, res = [root, ], []

        while stack:
            level = []
            for _ in range(len(stack)):
                node = stack.pop(0)
                level.append(node.val)
                if node.left:
                    stack.append(node.left)
                if node.right:
                    stack.append(node.right)
            res.append(level)
        return res

    def levelOrder2(self, root):
        from collections import deque
        if not root: return []
        queue, res = deque([root]), []

        while queue:
            level = []
            for _ in range(len(queue)):
                node = queue.popleft()
                level.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            res.append(level)
        return res

网上比较优秀的解法

解法一

广度优先遍历是按层层推进的方式,遍历每一层的节点。

广度优先需要用队列作为辅助结构,我们先将根节点放到队列中,然后不断遍历队列。

def levelOrder3(self, root):
        if not root: return []
        res = []
        def dfs(index, node):
            if len(res) < index:
                res.append([])
            res[index - 1].append(node.val)
            # 递归的处理左子树,右子树,同时将层数index+1
            if node.left:
                dfs(index + 1, node.left)
            if node.right:
                dfs(index + 1, node.right)
        dfs(1, root)
        return res

解法二

def levelOrder4(self, root):
        ans = []
        self.dfs(root, 0, ans)
        return ans

    def dfs(self, root, level, ans):
        if not root:
            return
        if len(ans) < level + 1:
            ans.append([])
        ans[level].append(root.val)
        self.dfs(root.left, level + 1, ans)
        self.dfs(root.right, level + 1, ans)

解法三

初始化: 当前层cur_level=[root],下一层next_level=[],结果集: [[i.val for i in cur_level]] 循环迭代更新当前层以及下一层,同时收集每一层结点值 循环结束条件:当前层以及下一层都为空

def levelOrder5(self, root):
        if not root: return []
        cur_level, nxt_level = [root], []    # 当前层结点以及下一层结点
        res = [[node.val for node in cur_level]]  # 遍历当前层

        while cur_level or nxt_level:
            for node in cur_level:
                if node.left:
                    nxt_level.append(node.left)
                if node.right:
                    nxt_level.append(node.right)
            if nxt_level:
                res.append([node.val for node in nxt_level])
            cur_level, nxt_level = nxt_level, []    # 更新当前层以及下一层

        return res

解法四

DFS 做本题的主要问题是: DFS 不是按照层次遍历的。为了让递归的过程中同一层的节点放到同一个列表中,在递归时要记录每个节点的深度 level。递归到新节点要把该节点放入 level 对应列表的末尾。 当遍历到一个新的深度 level,而最终结果 res 中还没有创建 level 对应的列表时,应该在 res 中新建一个列表用来保存该 level 的所有节点。

def levelOrder6(self, root):
        res = []
        self.level(root, 0, res)
        return res

    def level(self, root, level, res):
        if not root: return
        if len(res) == level: res.append([])
        res[level].append(root.val)
        if root.left:
            self.level(root.left, level + 1, res)
        if root.right:
            self.level(root.right, level + 1, res)

相关知识总结和思考

相关知识:

递归(recursion)就是子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己。该执行过程要求每一次节点中断调用其他方法,必须记录下该中断节点的环境信息,作用是为了调用结束返回结果之后原程序能够从上次中断位置起继续执行,在计算机中,通过一个栈结构来实现该效果(栈:先进后出):

递归与循环的区别与联系

相同点: (1)都是通过控制一个变量的边界(或者多个),来改变多个变量为了得到所需要的值,而反复而执行的; (2)都是按照预先设计好的推断实现某一个值求取;(请注意,在这里循环要更注重过程,而递归偏结果一点)

不同点: (1)递归通常是逆向思维居多,“递”和“归”不一定容易发现;而循环从开始条件到结束条件,包括中间循环变量,都需要表达出来。

简单的来说就是:用循环能实现的,递归一般可以实现,但是能用递归实现的,循环不一定能。因为有些题目

①只注重循环的结束条件和循环过程,而往往这个结束条件不易表达(也就是说用循环并不好写);

②只注重循环的次数而不注重循环的开始条件和结束条件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值