目录
leetcode题目
一、二叉树的层序遍历
二、二叉树的层序遍历 II
三、N叉树的层序遍历
四、二叉树的锯齿形层序遍历
五、二叉树最大宽度
六、在每个树行中找最大值
七、二叉树的层平均值
八、最大层内元素和
九、二叉树的第K大层和
十、反转二叉树的奇数层
leetcode题目
一、二叉树的层序遍历
102. 二叉树的层序遍历 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-level-order-traversal/
1.题目解析
二叉树的层序遍历
2.算法分析
树的层序遍历是典型要用到队列的场景,因为上一层遍历完之后,遍历下一层是从左到右,也就是要先遍历上一层最左节点的孩子,因此符合先进先出的原则,采用队列!
而题目要求返回二维数组,也就是把每一层遍历的节点放在同一个vector中,可是如何知道每一层的节点个数呢??? 只需要在元素出队列之前用变量记录一下队列当前元素的个数,就是该层节点的数量~
3.算法代码
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> vv;
if(root == nullptr) return vv;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
int levelSize = q.size();
vector<int> v;
while(levelSize--)
{
TreeNode* front = q.front();
q.pop();
v.push_back(front->val);
if(front->left)
q.push(front->left);
if(front->right)
q.push(front->right);
}
vv.push_back(v);
}
return vv;
}
};
二、二叉树的层序遍历 II
107. 二叉树的层序遍历 II - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/description/1.题目解析
自底向上层序遍历二叉树
2.算法分析
与题目一解法完全一样,最后将数组逆序一下即可~
3.算法代码
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>> vv;
if(root == nullptr) return vv;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
int levelSize = q.size();
vector<int> v;
while(levelSize--)
{
TreeNode* front = q.front();
q.pop();
v.push_back(front->val);
if(front->left)
q.push(front->left);
if(front->right)
q.push(front->right);
}
vv.push_back(v);
}
reverse(vv.begin(), vv.end());
return vv;
}
};
三、N叉树的层序遍历
429. N 叉树的层序遍历 - 力扣(LeetCode)https://leetcode.cn/problems/n-ary-tree-level-order-traversal/1.题目解析
N叉树的层序遍历
2.算法分析
与二叉树的层序遍历方法完全一致,区别就是一个节点可能有多个孩子,因此上一层出队列带下一层入队列,需要循环遍历把所有的孩子都带进来~
3.算法代码
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> ret;
queue<Node*> q;
if(root == nullptr) return ret;
q.push(root);
while(!q.empty())
{
int sz = q.size();
vector<int>tmp;
while(sz--)
{
Node* t = q.front();
q.pop();
tmp.push_back(t->val);
for(Node* child : t->children) //让下一层节点入队
{
if(child != nullptr)
q.push(child);
}
}
ret.push_back(tmp);
}
return ret;
}
};
四、二叉树的锯齿形层序遍历
103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/description/1.题目解析
相比之前题目,本题层序遍历是先从左往右,再从右往左,依次类推~
2.算法分析
增加一个标记位,让偶数层的数组逆序即可~
3.算法代码
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root)
{
vector<vector<int>> ret;
if(root == nullptr)
return ret;
queue<TreeNode*> q;
q.push(root);
int level = 1;
while(!q.empty())
{
int sz = q.size();
vector<int> tmp;
while(sz--)
{
TreeNode* front = q.front();
q.pop();
tmp.push_back(front->val);
if(front->left)
q.push(front->left);
if(front->right)
q.push(front->right);
}
//判断是否逆序
if(level % 2 == 0)
reverse(tmp.begin(), tmp.end());
ret.push_back(tmp);
level++;
}
return ret;
}
};
五、二叉树最大宽度
662. 二叉树最大宽度 - 力扣(LeetCode)https://leetcode.cn/problems/maximum-width-of-binary-tree/description/1.题目解析
每一层的宽度指的是某一层最左非空节点和最右非空节点之间的长度~
2.算法分析
二叉树根节点从1开始编号,创建一个队列,队列中存储的是<节点指针,节点编号>, 如果算上空节点的话那么二叉树就是满的,所以如果某个节点编号是x,那么左孩子节点编号是2*x, 右孩子节点编号是2*x+1, 每一层的长度就是 最右节点编号 - 最左节点编号 + 1, 而我们可以直接用vector来模拟队列~
3.算法代码
class Solution {
public:
int widthOfBinaryTree(TreeNode* root) {
vector<pair<TreeNode*, unsigned int>> q; //用数组模拟队列
q.push_back({root, 1});
unsigned int ret = 0; //统计最大宽度
while(!q.empty())
{
//更新这一层的最大宽度
auto& [x1, y1] = q[0];
auto& [x2, y2] = q.back();
ret = max(ret, y2 - y1 + 1);
//让下一层入队
vector<pair<TreeNode*, unsigned int>> tmp;
for(auto& [x, y] : q)
{
if(x->left) tmp.push_back({x->left, y * 2});
if(x->right) tmp.push_back({x->right, y * 2 + 1});
}
q = tmp;
}
return ret;
}
};
六、在每个树行中找最大值
515. 在每个树行中找最大值 - 力扣(LeetCode)https://leetcode.cn/problems/find-largest-value-in-each-tree-row/1.题目解析
找到二叉树每一行的最大值了,放在一个数组中,返回数组
2.算法分析
依旧是队列+宽搜,遍历每一层的时候用变量记录一下该层的最大值即可~
3.算法代码
class Solution {
public:
vector<int> largestValues(TreeNode* root)
{
vector<int> ret;
if(root == nullptr)
return ret;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
int sz = q.size();
int tmp = INT_MIN;
while(sz--)
{
auto t = q.front();
q.pop();
tmp = max(tmp, t->val);
if(t->left)
q.push(t->left);
if(t->right)
q.push(t->right);
}
ret.push_back(tmp);
}
return ret;
}
};
七、二叉树的层平均值
637. 二叉树的层平均值 - 力扣(LeetCode)https://leetcode.cn/problems/average-of-levels-in-binary-tree/1.题目解析
求二叉树每一行节点值的平均值,最后返回一个数组
2.算法分析
队列+宽搜,每一行求一下平均值即可~
3.算法代码
class Solution {
public:
vector<double> averageOfLevels(TreeNode* root)
{
vector<double> ret;
if(root == nullptr)
return ret;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
int sz = q.size();
double sum = 0;
for(int i = 0; i < sz; i++)
{
auto t = q.front();
q.pop();
sum += t->val;
if(t->left)
q.push(t->left);
if(t->right)
q.push(t->right);
}
double avg = sum / sz;
ret.push_back(avg);
}
return ret;
}
};
八、最大层内元素和
1161. 最大层内元素和 - 力扣(LeetCode)https://leetcode.cn/problems/maximum-level-sum-of-a-binary-tree/1.题目解析
返回元素和最大的那一层的层号
2.算法分析
队列+宽搜,求一下每一层的和,后续的层和大于之前的层和,就更新结果,同时记录层号
3.算法代码
class Solution
{
public:
int maxLevelSum(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
int ret = INT_MIN;
int retlevel = 0;
int level = 1;
while(!q.empty())
{
int sz = q.size();
int sum = 0;
while(sz--)
{
auto t = q.front();
q.pop();
sum += t->val;
if(t->left)
q.push(t->left);
if(t->right)
q.push(t->right);
}
if(ret < sum)
{
retlevel = level;
ret = sum;
}
level += 1;
}
return retlevel;
}
};
九、二叉树的第K大层和
2583. 二叉树中的第 K 大层和 - 力扣(LeetCode)https://leetcode.cn/problems/kth-largest-sum-in-a-binary-tree/1.题目解析
求二叉树的第K大层和,如果k > 树的层数,返回-1
2.算法分析
队列 + BFS + 优先级队列
3.算法代码
class Solution {
public:
long long kthLargestLevelSum(TreeNode* root, int k)
{
queue<TreeNode*> q;
q.push(root);
priority_queue<long long, vector<long long>, less<long long>> heap;
while(!q.empty())
{
int sz = q.size();
long long sum = 0;
while(sz--)
{
auto t = q.front();
q.pop();
sum += t->val;
if(t->left)
q.push(t->left);
if(t->right)
q.push(t->right);
}
heap.push(sum);
}
if(k > heap.size())
return -1;
while(--k)
heap.pop();
return heap.top();
}
};
十、反转二叉树的奇数层
2415. 反转二叉树的奇数层 - 力扣(LeetCode)https://leetcode.cn/problems/reverse-odd-levels-of-binary-tree/1.题目解析
将二叉树的奇数层进行反转,本题的根节点认为是第0层
2.算法分析
队列+BFS(宽搜),用level变量记录层数,如果是奇数层就将该层的节点指针插入到一个vector中,遍历完该层之后,将该层进行反转即可~
3.算法代码
class Solution {
public:
TreeNode* reverseOddLevels(TreeNode* root)
{
queue<TreeNode*> q;
q.push(root);
int level = 0;
vector<TreeNode*> tmp;
while(!q.empty())
{
int sz = q.size();
while(sz--)
{
auto t = q.front();
q.pop();
//奇数层的节点指针插入到tmp中
if(level % 2 == 1)
tmp.push_back(t);
if(t->left)
q.push(t->left);
if(t->right)
q.push(t->right);
}
//奇数层反转
if(level % 2 == 1)
{
int left = 0, right = tmp.size()-1;
while(left < right)
swap(tmp[left++]->val, tmp[right--]->val);
}
tmp.clear();
level++;
}
return root;
}
};