102.二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
思路
- 把根节点放入队列,队列不为空,继续循环
- 得到当前队列的大小,即这一层的节点数,作为下一次层序遍历的次数
- 当前队列的大小就是循环次数,所以每次遍历就加入到vec中,当循环结束就加入result中,一层就遍历完了
- 利用上一层的节点,获取左右孩子节点,push到队列中,为下一次遍历准备
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
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()){
// 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
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)
que.push(node->left);
if(node->right)
que.push(node->right);
}
result.push_back(vec);
}
return result;
}
};
递归法:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void order(TreeNode* cur,vector<vector<int>>& result, int depth)
{
if(cur == nullptr)
return;
if(result.size() == depth)
result.push_back(vector<int>());
result[depth].push_back(cur->val);
order(cur->left, result, depth + 1);
order(cur->right, result, depth + 1);
}
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
int depth = 0;
order(root, result, depth);
return result;
}
};
226.翻转二叉树
翻转一棵二叉树。
方法一:递归法
思路
递归三部曲:
- 确定递归函数的参数和返回值
- 确定终止条件(节点为空)
- 确定单层递归的逻辑(先前序遍历,左右交换,再依次反转左右子树)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
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;
}
};
复杂度分析
时间复杂度:O(N),其中 N为二叉树节点的数目。我们会遍历二叉树中的每一个节点,对每个节点而言,我们在常数时间内交换其两棵子树。
空间复杂度:O(N)。使用的空间由递归栈的深度决定,它等于当前节点在二叉树中的高度。在平均情况下,二叉树的高度与节点个数为对数关系,即 O(log N)。而在最坏情况下,树形成链状,空间复杂度为 O(N)。
方法二:迭代法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == NULL) return root;
stack<TreeNode*> st;
st.push(root);
while(!st.empty()) {
TreeNode* node = st.top(); // 中
st.pop();
swap(node->left, node->right);
if(node->right) st.push(node->right); // 右
if(node->left) st.push(node->left); // 左
}
return root;
}
};
方法三:层序遍历
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
swap(node->left, node->right); // 节点处理
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return root;
}
};
101. 对称二叉树
给定一个二叉树,检查它是否是镜像对称的。
方法一:递归法
思路
递归三部曲:
- 确定递归函数的参数和返回值
因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。
返回值是bool类型。
) - 确定终止条件(左右节点一个为空一个不为空/都不为空数值不相等,就是false,左右节点都为空就是true)
- 确定单层递归的逻辑(左右节点都不为空且数值相等,继续向下递归比较)注意比较有外层和内层
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool compare(TreeNode* left, TreeNode* right){
if (left == NULL && right != NULL) return false;
else if (left != NULL && right == NULL) return false;
else if (left == NULL && right == NULL) return true;
// 排除了空节点,再排除数值不相同的情况
else if (left->val != right->val) return false;
// 此时就是:左右节点都不为空,且数值相同的情况
// 此时才做递归,做下一层的判断
bool outside = compare(left->left, right->right);
bool inside = compare(left->right, right->left);
bool isSame = outside && inside;
return isSame;
}
bool isSymmetric(TreeNode* root) {
if(root == NULL) return true;
return compare(root->left, root->right);
}
};
复杂度分析
假设树上一共 n 个节点。
时间复杂度:这里遍历了这棵树,渐进时间复杂度为 O(n)。
空间复杂度:这里的空间复杂度和递归使用的栈空间有关,这里递归层数不超过 n,故渐进空间复杂度为 O(n)。
方法二:迭代法(使用队列)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root == NULL) return true;
queue<TreeNode*> que;
que.push(root->left);
que.push(root->right);
while(!que.empty()){
TreeNode* leftNode = que.front();
que.pop();
TreeNode* rightNode = que.front();
que.pop();
if(!leftNode && !rightNode){ //左右节点同时为空是对称的,所以跳过
continue;
}
//左右节点一个为空一个不为空,或者数值不相等,就不是对称的
//都为空就继续判断
if(!leftNode || !rightNode ||(leftNode->val != rightNode->val)){
return false;
}
//队列弹出,所以要按照顺序,前两行为外面,后两行为里面
que.push(leftNode->left);
que.push(rightNode->right);
que.push(leftNode->right);
que.push(rightNode->left);
}
return true;
}
};
复杂度分析
时间复杂度:O(n)
空间复杂度:这里需要用一个队列来维护节点,每个节点最多进队一次,出队一次,队列中最多不会超过 n 个点,故渐进空间复杂度为 O(n)。
方法三:迭代法(使用栈)
和队列差不多
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (root == NULL) return true;
stack<TreeNode*> st; // 这里改成了栈
st.push(root->left);
st.push(root->right);
while (!st.empty()) {
TreeNode* leftNode = st.top(); st.pop();
TreeNode* rightNode = st.top(); st.pop();
if (!leftNode && !rightNode) {
continue;
}
if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {
return false;
}
st.push(leftNode->left);
st.push(rightNode->right);
st.push(leftNode->right);
st.push(rightNode->left);
}
return true;
}
};