102.二叉树层序遍历
一、做题感受&第一想法
用队列实现,用NULL隔开各层元素。
二、学习文章后收获
逐层遍历:
对于每层结点,提前统计当前queue中的元素个数size,然后用for循环遍历这size个元素。
注:要事先记录下queue的size,因为que.size()在之后的过程中会改变!
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
TreeNode* cur = NULL;
vector<vector<int>> result;
vector<int> v;
if(root) que.push(root);
while(!que.empty()){
int size = que.size(); //要事先记录下que的size,因为que.size()在之后的过程中会改变!
v.clear();
for(int i = 0;i < size;i++){
cur = que.front();
que.pop();
v.push_back(cur->val);
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
result.push_back(v);
}
return result;
}
};
三、过程中遇到的问题
1.pop()操作没有返回值
stack和queue的pop()都没有返回值!
stack.top()
是栈顶元素
queue.front()
是队头元素
(层序遍历的递归形式还没看)
层序遍历其他题目(未更完)
-
107.二叉树的层序遍历 II:先层序遍历,再reverse。
-
199.二叉树的右视图:(单纯的“优先向右遍历”是不行的,必须要层序遍历!)层序遍历,输出每层的最后一个元素。
-
637.二叉树的层平均值:层序遍历,记录每层的和,和每层节点个数size。
-
429.N叉树的层序遍历 :关键在于遍历每个节点的
vector<Node*> children
。
226. 翻转二叉树
一、做题感受&第一想法
遍历+左右孩子互换。
遍历尝试了“层序”和“迭代统一写法的中序”。
没有想到递归法。
二、学习文章后收获
1.方法:
- 整体思路:遍历+左右节点左右孩子互换
- 适用的遍历方法:
- 递归:递归的后序、递归的先序都可,但是递归的中序不可(除非稍作修改)。
- 非递归:层序可以,迭代的先序、后序都可以,中序的迭代统一写法可以。
2.递归代码
- 递归,先序
class Solution {
public:
void swap(TreeNode* t){
TreeNode* temp;
temp = t->left;
t->left = t->right;
t->right = temp;
}
TreeNode* invertTree(TreeNode* root) {
if(root == NULL) return root;
swap(root);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
- 递归,中序
class Solution {
public:
void swap(TreeNode* t){
TreeNode* temp;
temp = t->left;
t->left = t->right;
t->right = temp;
}
TreeNode* invertTree(TreeNode* root) {
if(root == NULL) return root;
invertTree(root->left);
swap(root);
invertTree(root->left); //注意这里!
return root;
}
};
101. 对称二叉树
一、做题感受&第一想法
方法一:
(我自己的方法)
层序遍历,并用deque来记录每层节点,然后判断deque是否对称。
(注意:对从deque中弹出的元素,如果左/右孩子为NULL也需要记录在deque里!但如果从deque中直接弹出NULL,不用压入两个NULL,否则循环无法退出!)
class Solution {
public:
bool isSymmetric(TreeNode* root) {
deque<TreeNode*> deq;
TreeNode* cur;
if(root){
deq.push_front(root->left);
deq.push_back(root->right);
}
while(!deq.empty()){
int size = deq.size();
deque<TreeNode*>::iterator it_front = deq.begin();
deque<TreeNode*>::iterator it_back = deq.end()-1;
//比较deque的前半段和后半段是否相同
for(int i = 0;i < size/2;i++){
if(*it_front && *it_back && (*it_front)->val == (*it_back)->val){
it_back--;
it_front++;
continue;
}
else if(*it_back == NULL && *it_front == NULL){
it_back--;
it_front++;
continue;
}
else{
return false;
}
}
//把deque里的数据更新成下一层的节点。
for(int i = 0;i < size;i++){
cur = deq.front();
deq.pop_front();
if(cur){
deq.push_back(cur->left);
deq.push_back(cur->right);
}
}
}
return true;
}
};
二、学习文章后收获
方法二:递归法
- 传递参数和返回值:参数是要比较是否对称的两个节点,返回值是比较的结果
- 本层内需要做的处理:针对这两个节点,判断是否对称(①如果两节点全空,则返回true。②如果两节点全不空,而且val相等,则继续检查对应的“内侧两节点”和“外侧两节点”是否对称。③除此之外,都不对称,都返回false。)
- 返回条件:上一点已说明。
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root) return myCompare(root->left,root->right);
else return true;
}
bool myCompare(TreeNode* node1,TreeNode* node2){
if(node1 == NULL && node2 == NULL) return true;
else if(node1 != NULL && node2 != NULL && node1->val == node2->val){
bool compareInside = myCompare(node1->right,node2->left);
bool compareOutside = myCompare(node1->left,node2->right);
return compareInside && compareOutside;
}
else return false;
}
};
方法三:队列+迭代法
其实方法三和方法四(队列和栈)本质上都是通过可存储的数据结构来暂存待处理的节点,主要是要确定入队列/栈的顺序,你维护的数据结构要让之后每次弹出的两个相邻元素都是“对称位置”上的元素。
注:如果孩子有NULL,也会入队/栈。但是NULL的孩子NULL不会再入队/栈了。
class Solution {
public:
bool isSymmetric(TreeNode* root) {
queue<TreeNode*> q;
TreeNode* node1 = NULL, *node2 = NULL;
if(root){
q.push(root->left);
q.push(root->right);
}
while( !q.empty() ){
node1 = q.front();
q.pop();
node2 = q.front();
q.pop();
if(node1 == NULL && node2 == NULL) continue;
else if(node1 == NULL && node2 != NULL) return false;
else if(node1 != NULL && node2 == NULL) return false;
else if(node1 != NULL && node2 != NULL && node1->val != node2->val) return false;
else if(node1 != NULL && node2 != NULL && node1->val == node2->val){
q.push(node1->left);
q.push(node2->right);
q.push(node1->right);
q.push(node2->left);
}
}
return true;
}
};
方法四:栈+迭代法
class Solution {
public:
bool isSymmetric(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* node1 = NULL, *node2 = NULL;
if(root){
st.push(root->left);
st.push(root->right);
}
while( !st.empty() ){
node1 = st.top();
st.pop();
node2 = st.top();
st.pop();
if(node1 == NULL && node2 == NULL) continue;
else if(node1 == NULL && node2 != NULL) return false;
else if(node1 != NULL && node2 == NULL) return false;
else if(node1 != NULL && node2 != NULL && node1->val != node2->val) return false;
else if(node1 != NULL && node2 != NULL && node1->val == node2->val){
st.push(node1->left);
st.push(node2->right);
st.push(node1->right);
st.push(node2->left);
}
}
return true;
}
};
三、过程中遇到的问题
1.运算符优先级
->
优先级巨高,高于*
。
错误写法:*iterator->val
正确写法:(*iterator)->val
报错信息:
Line 27: Char 73: error: member reference base type ‘TreeNode *’ is not a structure or union
27 | if(*it_front && *it_back && (*it_front)->val == *it_back->val){
| ~~~^
1 error generated.