102. 二叉树的层序遍历
层序遍历是一种树遍历方法,其中每个节点都被访问一次,并且每个节点都按照从上到下、从左到右的顺序被访问。
代码中定义了一个名为Solution
的类,该类中包含一个公共成员函数levelOrder
,它接收一个指向二叉树根节点的指针root
,并返回一个二维整数向量,表示二叉树的层序遍历结果。
levelOrder
函数使用了队列数据结构来实现层序遍历。首先,如果根节点不为空,将其加入队列。然后,进入循环,直到队列为空为止。在每次循环中,先获取当前队列的大小(即当前层的节点数),然后创建一个整数向量vec
来存储当前层的节点值。接下来,通过循环访问队列中的每个节点,将其值加入vec
向量,并将其左右子节点(如果存在)加入队列。最后,将vec
向量加入结果向量result
中。
在循环内部,注释提到了一个重要注意事项:在循环中使用固定大小size
来限制循环次数,而不是使用动态变化的que.size()
。这是因为队列的大小在循环过程中会不断变化,如果使用que.size()
作为循环条件,会导致循环次数不正确。
最终,函数返回结果向量result
,其中包含了二叉树的层序遍历结果。
这个程序的时间复杂度是O(n),其中n是二叉树的节点数。因为每个节点只被访问一次,并且访问每个节点的操作都是常数时间的。空间复杂度也是O(n),因为需要使用一个队列来存储每一层的节点。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
vector<vector<int>> result;
while (!que.empty()) {
int size = que.size();
vector<int> vec;
// 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
vec.push_back(node->val);
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
result.push_back(vec);
}
return result;
}
};
107. 二叉树的层序遍历II
只是在最后反转一下就可以
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
queue<TreeNode *> que;
if(root != nullptr) que.push(root);
vector<vector<int>> result;
while(!que.empty())
{
int size =que.size();
vector<int> vec;
for (int i = 0; i < size; i++)
{
TreeNode *node = que.front();
que.pop();
vec.push_back(node->val);
if(node->left != nullptr)
que.push(node->left);
if(node->right != nullptr)
que.push(node->right);
}
result.push_back(vec);
}
reverse(result.begin(), result.end());
return result;
}
};
199.二叉树的右视图
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
vector<int> result;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
if (i == (size - 1)) result.push_back(node->val);
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
if (i == (size - 1)) result.push_back(node->val); 可以将一行中最后一个放入result中
637.二叉树的层平均值
for循环负责循环同行里面的元素,sum会在一行结束之后归零,以实现累加操作
class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
queue<TreeNode*> que;
if(root!=nullptr) que.push(root);
vector<double> result;
while(!que.empty())
{
int size = que.size();
double sum = 0;
for(int i = 0; i < size;i++)
{
TreeNode* node=que.front();
que.pop();
sum += node->val;
if(node->left)
que.push(node->left);
if(node->right)
que.push(node->right);
}
result.push_back(sum/size);
}
return result;
}
};
226反转二叉树
递归三步:确定元素和返回值;确定单层递归逻辑;确定结束条件
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == nullptr) return root;
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
这里采用的是前序遍历,也可以使用后序遍历,但是不可以使用中序遍历,会导致先反转的树枝再次被反转过来
101.对称二叉树
思路:可以用刚才的反转二叉树与测试的二叉树比较,但是地址问题存在
class Solution {
public:
TreeNode *invertTree(TreeNode *root)
{
if (root == nullptr)
return root;
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
bool isSymmetric(TreeNode* root) {
if(root == nullptr)return true;
return root==invertTree(root)?true:false;
}
};
首先对于五特殊情况:
1.左空右空2.左空右不空3.左不空右空4.下层left right不等5.下层left right相等
1.true2.false3.false4.false5.递归遍历下一层
class Solution {
public:
bool compare(TreeNode *left, TreeNode *right)
{
if(left == nullptr && right != nullptr) return false;
else if(left != nullptr && right == nullptr) return false;
else if(left == nullptr && right == nullptr) return true;
else if (left->val != right->val)
return false;
bool outsider=compare(left->left, right->right);
bool insider=compare(left->right, right->left);
bool issame = (outsider && insider);
return issame;
}
bool isSymmetric(TreeNode* root) {
if(root == nullptr)return true;
return compare(root->left, root->right);
}
};
提示必须先排除空指针,不可先检查,会导致出错。