按层次遍历二叉树_107.二叉树的层次遍历 II

题目描述

给定一个二叉树,返回其节点值自底向上的层次遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

例如:
给定二叉树[3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其自底向上的层次遍历为:

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

迭代实现

迭代遍历比较直观,就是按层遍历

98d262f7a493d4df07135e283d57f1af.png

我们将我们一层遍历得到的结果放到一个数组中,等这一层遍历完后,将这个数组放入到最终结果集res中。
因为题目要求是反序输出,所以我们只需将res翻转一下就可以了。

我们看下如何实现这个迭代遍历

2dccd43844a5fcc235380c2663c8534b.png

如上图,首先创建一个队列,将根节点root放入队列中,然后不断循环遍历这个队列。
对于树的第一层,其长度为1,而此时根节点也放到队列中了,所以队列的长度也是1,我们取出一个元素,将其放入临时数组中。
如果这个节点的左右孩子不为空,则将他们也放入队列中。

6fcf0f75ecd76c06ea3a55055d989667.png

上图是处理第二层的过程,类似于第一层,由于第一层遍历完后,队列里有两个元素了,所以第二次遍历的时候,可以确定队列长度是2,于是执行两次,将23取出,放入临时数组中,之后再将23的两个孩子也放入队列中。
处理第三层时,队列长度就是4了,于是取出4个元素,再次处理。

java代码:

class Solution {
    public List> levelOrderBottom(TreeNode root) {if(root==null) {return new ArrayList>();
        }//用来存放最终结果
        ArrayList> res = new ArrayList>();//创建一个队列,将根节点放入其中
        Queue queue = new LinkedList();
        queue.offer(root);while(!queue.isEmpty()) {//每次遍历的数量为队列的长度int size = queue.size();
            ArrayList tmp = new ArrayList();//将这一层的元素全部取出,放入到临时数组中,如果节点的左右孩子不为空,继续放入队列for(int i=0;i                TreeNode node = queue.poll();
                tmp.add(node.val);if(node.left!=null) {
                    queue.offer(node.left);
                }if(node.right!=null) {
                    queue.offer(node.right);
                }
            }
            res.add(tmp);
        }//翻转最终结果并返回
        Collections.reverse(res);return res;
    }
}

python代码:

class Solution(object):
    def levelOrderBottom(self, root):
        if not root:
            return []
        # 创建一个队列,将根节点放入其中    
        queue = [root]
        # 用来存放最终结果
        res = []
        while queue:
            # 每次遍历的数量为队列的长度
            size = len(queue)
            tmp = []
            # 将这一层的元素全部取出,放入到临时数组中,如果节点的左右孩子不为空,继续放入队列
            for _ in xrange(size):
                node = queue.pop(0)
                tmp.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            res.append(tmp)
        # 翻转最终结果并返回
        return res[::-1]

迭代实现-2

第一种方式中,我们将最终结果集定义成数组,等所有元素都放置完后,再翻转一下数组。
我们可以将最终结果集改成链表,以后每层遍历完将结果放入到链表的第一位,这样就自动完成了翻转的功能了。

java代码:

class Solution {
    public List> levelOrderBottom(TreeNode root) {if(root==null) {return new ArrayList>();
        }//改用链表实现,每次都插入到第一位
        LinkedList> res = new LinkedList>();
        Queue queue = new LinkedList();
        queue.offer(root);while(!queue.isEmpty()) {int size = queue.size();
            ArrayList tmp = new ArrayList();for(int i=0;i                TreeNode node = queue.poll();
                tmp.add(node.val);if(node.left!=null) {
                    queue.offer(node.left);
                }if(node.right!=null) {
                    queue.offer(node.right);
                }
            }//每次都保存到链表的第一位,这样自带了翻转的功能
            res.add(0,tmp);
        }return res;
    }
}

python代码:

class Solution(object):
    def levelOrderBottom(self, root):
        if not root:
            return []
        queue = [root]
        # 改用双端队列实现,每次都插入到第一位
        res = collections.deque()
        while queue:
            size = len(queue)
            tmp = []
            for _ in xrange(size):
                node = queue.pop(0)
                tmp.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            # 每次插入到第一位,这样自带了翻转的功能       
            res.appendleft(tmp)
        return list(res)

递归实现

递归实现就不那么直观了,我们可以把二叉树结构改变一下,想象成一个三角形的结构 我们在递归遍历时,将第一层的元素放入到第一层的数组中,将第二层的的元素放入到第二层,第三层的元素放入第三层。第三层的4是在5之前被遍历的,所以放入到第三层数组时,4就在5前面,同理6是在7前面被遍历的,所以放入到第三层时6就在7前面。

6cdcb3d4a9642f7a33a1c73cc652d051.png

这次我们不用创建队列了,直接在最终结果集res上操作,res是个二维数组,集合中嵌套集合,但现在没有任何嵌套的集合。

9eac422f88b0d31cf73ba3065a8f82a6.png

如上图所示,一开始res是空的,当遍历到第一层时候,我们创建一个集合,放入res,然后将第一层的1,放到res[0]中。
遍历到第二层时,再创建一个集合放入res,然后将2放入res[1]中。
遍历到第三层时,同样再创建一个集合放入res,将4放入res[2]中。
当我们再回到第三层,遍历到5时,就不用再创建新集合了,直接将5放到到res[2]中即可。
之后,再将3放到res[1]67放入res[2]中。

完整的遍历过程如下图:

737eb46606cd811aa1f9dccf5cf58ddd.gif

java代码:

class Solution {
    public List> levelOrderBottom(TreeNode root) {if(root==null) {return new ArrayList>();
        }//用来存放最终结果
        ArrayList> res = new ArrayList>();
        dfs(root,res,1);
        Collections.reverse(res);return res;
    }private void dfs(TreeNode root,ArrayList> res,int index) {if(root==null) {return;
        }//如果index大于res大小,说明这一层没有对应的集合,需要新创建if(index>res.size()) {
            res.add(new ArrayList());
        }//将当前层的元素直接放到对应层的末尾即可
        res.get(index-1).add(root.val);//继续遍历左右节点,同时将层高+1
        dfs(root.left,res,index+1);
        dfs(root.right,res,index+1);
    }
}

python代码:

class Solution(object):
    def levelOrderBottom(self, root):
        if not root:
            return []
        # 用来存放最终结果    
        res = []
        def dfs(root,index):
            if not root:
                return
            # 如果index大于res大小,说明这一层没有对应的集合,需要新创建    
            if index>len(res):
                res.append([])
            # 将当前层的元素直接放到对应层的末尾即可    
            res[index-1].append(root.val)
            # 继续遍历左右节点,同时将层高+1
            dfs(root.left,index+1)
            dfs(root.right,index+1)
        dfs(root,1)
        return res[::-1]
如果觉得不错又懒得留言 你可以点个在看7f1a92486a7a0585c32eca91c4ea4c40.png7f1a92486a7a0585c32eca91c4ea4c40.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值