vlambda博客
学习文章列表

二叉树刷题篇(3)层序遍历

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

https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

这个没什么好说的,用队列存储节点,然后用size存储大小,这样可以保证每次处理的数据是自己想要的数据。

代码如下。

class Solution {public: vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> ans; queue<TreeNode*> que; if(root!=NULL) que.push(root); while(!que.empty()){ int size=que.size(); vector<int> layer; for(int i=0;i<size;i++){ TreeNode* cur=que.front(); layer.push_back(cur->val); que.pop(); if(cur->left!=NULL) que.push(cur->left); if(cur->right!=NULL) que.push(cur->right); } ans.push_back(layer); } return ans; }};

解决完这道题,我们来看下一位选手:二叉树层序遍历II。emmmm,小兄弟,你确定不是来送人头的?在第一题的基础上,只需简单的修改即可。

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

https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/submissions/

给出一段神秘代码就可以解决这道题,reverse(ans.begin(),ans.end());你猜猜加在哪?

再来看三号选手,199.二叉树的右视图

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

https://leetcode-cn.com/problems/binary-tree-right-side-view/

首先一定要避免一个思维误区,即简单地认为一直向着右边遍历下去就可以。(不会吧不会吧,不会真有人这么傻吧……二叉树刷题篇(3)层序遍历比如我自己哈哈哈)

最好想的思路应该是将层序遍历每一层的最后一个数作为答案输出。实现方法应该也很简单,在层序遍历的代码中加入判断,当每层循环到size次时,才将节点数值push到向量中。

class Solution {public: vector<int> rightSideView(TreeNode* root) { queue<TreeNode*> que; vector<int> ans; if(root!=NULL) que.push(root); while(!que.empty()){ int size=que.size(); for(int i=0;i<size;i++){ TreeNode* cur=que.front(); if(i==size-1) ans.push_back(cur->val); que.pop(); if(cur->left!=NULL) que.push(cur->left); if(cur->right!=NULL) que.push(cur->right);  } } return ans; }};

直接贴代码……一次成功!下一题!637.二叉树的层平均值。

给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。

https://leetcode-cn.com/problems/average-of-levels-in-binary-tree/

怎么说呢,只要二叉树的层序遍历熟练掌握,这些题真的都很简单,直接上代码。与之前的不同就是需要在i==size-1时计算下平均值,这里需要注意,因为我们把之前的值已经pop掉了,所以需要一个额外的变量sum来记录总的值。sum/size就是我们想要的平均值。

当然,这里还有一种方法是在for循环后进行平均值的计算,这样显然会更直观,更简洁。

class Solution {public: vector<double> averageOfLevels(TreeNode* root) { queue<TreeNode*> que; vector<double> ans; if(root!=NULL) que.push(root); while(!que.empty()){ int size=que.size(); double sum=0; for(int i=0;i<size;i++){ TreeNode* cur=que.front(); sum+=cur->val; if(i==size-1) ans.push_back(sum/size); que.pop(); if(cur->left!=NULL) que.push(cur->left); if(cur->right!=NULL) que.push(cur->right);  } } return ans; }};

最后是五娃,429.N叉树的层序遍历。

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。

https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/


看来五娃稍稍不一样,实际上不同的地方也只在于N叉树与二叉树的不同,其实我对N叉树的结构也不是很熟悉,为了避免出错,我们还是先看一下Leetcode官方给出的N叉树的定义。

/*// Definition for a Node.class Node {public: int val; vector<Node*> children;
Node() {}
Node(int _val) { val = _val; }
Node(int _val, vector<Node*> _children) { val = _val; children = _children; }};*/

看来N叉树和二叉树区别并不大(这不是废话吗~),只是存储其孩子的容器变成了vector,事不宜迟,直接开写代码。

class Solution {public: vector<vector<int>> levelOrder(Node* root) { queue<Node*> que; if (root != NULL) que.push(root); vector<vector<int>> result; while (!que.empty()) { int size = que.size(); vector<int> vec; for (int i = 0; i < size; i++) {  Node* node = que.front(); que.pop(); vec.push_back(node->val); for (int i = 0; i < node->children.size(); i++) { // 将节点孩子加入队列 if (node->children[i]) que.push(node->children[i]); } } result.push_back(vec); } return result;
}};

依然是没有什么太大的难度,但第一次接触N叉树的确需要一段时间来熟悉,今天就到这里吧。这几道题让人久违的有了做题的感觉(做题家实锤了),会一道等于会五道,争取以后也能够有类似这样举一反三,融会贯通的体验吧~