层序遍历
102.二叉树的层序遍历
通过队列实现
基本算法,每次把一层的节点放入栈中
/**
* 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*> q;
vector<vector<int>> res;
if (root == nullptr)
return res;
q.push(root);
while (!q.empty()) {
int size = q.size();
vector<int> r;
for (int i = 0; i < size; i++) {
TreeNode* t = q.front();
q.pop();
r.push_back(t->val);
if (t->left)
q.push(t->left);
if (t->right)
q.push(t->right);
}
res.push_back(r);
}
return res;
}
};
通过递归实现
递归的三要素
-
确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
-
确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
-
确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
1.参数:指针,结果数组,当前层数
2.终止条件:当前指针为空就返回,如果指针来到一个新层,就给结果数组里添加一个空数组
3.单层逻辑:遍历到一个新节点就放入该层的数组中,之后再考虑遍历其左右孩子,其实递归的访问顺序没有满足层序遍历(满足前序遍历),因为一直在访问左孩子,但是res[depth].push_back(cur->val)
确保了访问的节点填入到对应的层的数组中的正确位置
/**
* 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 lorder(TreeNode* cur,vector<vector<int>>& res,int depth){
if(cur == nullptr) return;
// 遍历到当前新层时,需要 新添加一个数组
if(res.size() == depth) res.push_back(vector<int>());
res[depth].push_back(cur->val);
lorder(cur->left,res,depth+1);
lorder(cur->right,res,depth+1);
}
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
if(root ==nullptr) return res;
lorder(root,res,0);
return res;
}
};
199.二叉树的右视图
使用层序遍历,记录每一层的最后一个节点即可(cur)
/**
* 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<int> rightSideView(TreeNode* root) {
vector<int> res;
if(root == nullptr) return res;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int size = q.size();
TreeNode* cur;
for(int i = 0; i < size; i++){
cur = q.front();
q.pop();
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
}
// cur最后指向的是本层最后一个元素
res.push_back(cur->val);
}
return res;
}
};
637.二叉树的层平均值
统计每层的和即可
/**
* 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<double> averageOfLevels(TreeNode* root) {
vector<double> res;
if(root == nullptr) return res;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
double sum = 0;
int size = q.size();
for(int i = 0; i < size; i++){
TreeNode* cur = q.front();
q.pop();
sum += cur->val;
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
}
res.push_back(sum / size);
}
return res;
}
};
429.N叉树的层序遍历
同理,只是把左右孩子节点的遍历更换成了遍历vector数组,同时需要判定某个孩子是否为null
/*
// 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;
}
};
*/
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> res;
if(root == NULL) return res;
queue<Node*> q;
q.push(root);
while(!q.empty()){
int size = q.size();
vector<int> r;
for(int i = 0; i < size; i++){
Node* cur = q.front();
q.pop();
r.push_back(cur->val);
for(int j = 0; j < cur->children.size(); j++){
if(cur->children[j] != NULL) q.push(cur->children[j]);
}
}
res.push_back(r);
}
return res;
}
};
515.在每个树行中找最大值
在每一层找最大值即可
/**
* 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<int> largestValues(TreeNode* root) {
vector<int> res;
if(root == nullptr) return res;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int size = q.size();
int maxn = INT_MIN;
for(int i =0; i<size;i++){
TreeNode* cur = q.front();
maxn = max(maxn,cur->val);
q.pop();
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
}
res.push_back(maxn);
}
return res;
}
};
116.填充每个节点的下一个右侧节点指针
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
Node* cur;
if(root == NULL) return root;
queue<Node*> q;
q.push(root);
while(!q.empty()){
int size = q.size();
vector<Node*> r;
for(int i = 0; i <size; i++){
cur = q.front();
q.pop();
r.push_back(cur);
if(cur->left!=NULL) q.push(cur->left);
if(cur->right!=NULL) q.push(cur->right);
}
r.push_back(NULL);
for(int i = 0; i < size; i++){
r[i]->next = r[i+1];
}
}
return root;
}
};
104.二叉树的最大深度
层序遍历计算层数
/**
* 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:
int maxDepth(TreeNode* root) {
int depth = 0;
if(root == nullptr) return 0;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int size = q.size();
depth++;
for(int i = 0; i < size;i++){
TreeNode* cur = q.front();
q.pop();
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
}
}
return depth;
}
};
DFS解法
/**
* 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:
// 1.参数只需要指针
int maxDepth(TreeNode* root) {
// 2.判断递归终止条件
if(root == nullptr) return 0;
// 3.确定递归逻辑,使用后续遍历访问顺序,获取左子树和右子树中的深度,取最大值
int left = maxDepth(root->left);
int right = maxDepth(root->right);
return max(left,right) + 1;
}
};
111.二叉树最小深度
记录当前深度,如果碰见某个节点左右孩子都为空,则表示其为叶节点,说明该层就是最小深度。
如果题目改为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:
int minDepth(TreeNode* root) {
if(root == nullptr) return 0;
queue<TreeNode*> q;
q.push(root);
int depth = 0;
while(!q.empty()){
int size = q.size();
depth++;
for(int i = 0; i < size;i++){
TreeNode* cur = q.front();
q.pop();
if(cur->left==nullptr && cur->right==nullptr) return depth;
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
}
}
return depth;
}
};
翻转二叉树
使用后序遍历(前序遍历也可)
/**
* 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 nullptr;
TreeNode* left = invertTree(root->left);
TreeNode* right = invertTree(root->right);
root->left = right;
root->right = left;
return root;
}
};
前序遍历(迭代)
/**
* 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;
stack<TreeNode*> st;
st.push(root);
while (!st.empty()) {
TreeNode* cur = st.top();
st.pop();
if (cur != NULL) {
if (cur->right)
st.push(cur->right);
if (cur->left)
st.push(cur->left);
st.push(cur);
st.push(NULL);
} else {
TreeNode* t = st.top();
st.pop();
swap(t->left, t->right);
}
}
return root;
}
};
对称二叉树
个人想法:用层序遍历来检查:除了第一层的其他层里,节点个数是否为偶数且对称
/**
* 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 check(vector<TreeNode*> r) {
int mid = r.size() / 2;
for (int i = mid - 1, j = mid; i >= 0 && j < r.size(); i--, j++) {
if (r[i] == NULL && r[j] == NULL)
continue;
if (r[i] != NULL && r[j] != NULL && r[i]->val == r[j]->val)
continue;
else
return false;
}
return true;
}
bool isSymmetric(TreeNode* root) {
if (root == NULL)
return false;
queue<TreeNode*> q;
q.push(root);
TreeNode* cur;
while (!q.empty()) {
int size = q.size();
if (size % 2 != 0 && q.front() != root)
return false;
vector<TreeNode*> r;
for (int i = 0; i < size; i++) {
cur = q.front();
q.pop();
r.push_back(cur);
// 这里注意,这种操作保证了将NULL放入队列,且遍历到NULL的时候不会继续入队列
if(cur != NULL){
q.push(cur->left);
q.push(cur->right);
}
}
if (cur == root)
continue;
if (!check(r))
return false;
}
return 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 Symmetric(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;
// 如果left和right相等不能直接return true,因为要进入下一层判断
bool outside = Symmetric(left->left,right->right);
bool inside = Symmetric(left->right,right->left);
return outside && inside;
}
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
return Symmetric(root->left,root->right);
}
};
迭代法:
把队列改成栈也行
/**
* 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 == nullptr)
return true;
queue<TreeNode*> q;
q.push(root->left);
q.push(root->right);
while (!q.empty()) {
TreeNode* left = q.front();
q.pop();
TreeNode* right = q.front();
q.pop();
if (left == nullptr && right == nullptr)
continue;
else if (left != nullptr && right == nullptr)
return false;
else if (left == nullptr && right != nullptr)
return false;
else if (left->val != right->val)
return false;
q.push(left->left);
q.push(right->right);
q.push(left->right);
q.push(right->left);
}
return true;
}
};