关于层序遍历的recursion递归法
!!!尽管层序遍历的recursion方法能够生成按层级组织的输出,但它的遍历方式实际上是dfs
在开头总结下这10道题:
基础模板:102,107,199,429
适合用bfs迭代,不推荐用dfs/递归(因为要同层内操作):637,515,116,117
bfs dfs都可:找深度 104, 111 (这一章是层次遍历,我们找深度的题都可以直接当层次遍历的模板题,之后博客还会详细讨论“深度”题型)
1. 102 基本款层序遍历
层序遍历-迭代法
注意:用固定大小size来遍历
vector> levelOrder(TreeNode* root) {
vector> res;
queue myq;
if(root!=nullptr) myq.push(root);
while(!myq.empty()){
int size=myq.size();
vector vec;
//此处一定要用固定大小size,因为不断操作myq,用queue.size()会变
for(int i=0;ival);
myq.pop();
if(node->left!=nullptr) myq.push(node->left);
if(node->right!=nullptr) myq.push(node->right);
}
res.push_back(vec);
}
return res;
}
层序遍历-递归法
易错:传入的变量到底是var还是ref
如何想明白:如果depth传的是ref的话,if(node->left!=nullptr)order(node->left,depth+1,res);这个执行完到下一句right那里,depth就会变,但不能让他变
void order(TreeNode* node, int depth, vector> &res){
//depth 不應該傳入ref很重要,因爲遞歸的歸 return
//比如left做完回來的時候,depth不應該變
if(node==nullptr)return;
if(res.size()==depth)res.push_back(vector());
res[depth].push_back(node->val);
if(node->left!=nullptr)order(node->left,depth+1,res);
if(node->right!=nullptr)order(node->right,depth+1,res);
}
vector> levelOrder(TreeNode* root) {
vector> res;
int depth=0;
order(root, depth, res);
return res;
}
以上是探讨dfs&bfs实现的区别
2. 107 层序遍历从最下层开始 易变体: 迭代ok 递归ok 都是最基本的+vec反一下就行;
vector> levelOrderBottom(TreeNode* root) {
//想到幾種方法:1 放入 stack來反過來
//2 用雙指針把vec 做reverse
//3 用庫函數做reverse
vector> res;
queue myq;
if(root!=nullptr) myq.push(root);
TreeNode *node;
while(!myq.empty()){
int size=myq.size();
vector vec;
for(int i=0;ival);
myq.pop();
if(node->left!=nullptr) myq.push(node->left);
if(node->right!=nullptr) myq.push(node->right);
}
res.push_back(vec);
}
//reverse(res.begin(),res.end());
int i=0; int j=res.size()-1;
while(i
3. 199 层序右视图 易变体,迭代ok:pushback vec改成if(i==size-1) res.push_back(node->val); 即可
vector rightSideView(TreeNode* root) {
vector res;
queuemyq;
TreeNode* node;
if(root!=nullptr) myq.push(root);
while(!myq.empty()){
int size=myq.size();
for(int i=0;ileft!=nullptr) myq.push(node->left);
if(node->right!=nullptr) myq.push(node->right);
if(i==size-1) res.push_back(node->val);
}
}
return res;
}
递归ok
void traverse(TreeNode* node, int depth, vector &res){
if(node==nullptr) return;
if(depth==res.size()) res.push_back(0);
res[depth]=node->val;
//关键是前面这两行,一开始觉得很难找到一层最后一个
//后来发现每个新的来了覆盖就行
if(node->left!=nullptr) traverse(node->left, depth+1, res);
if(node->right!=nullptr) traverse(node->right, depth+1, res);
}
vector rightSideView(TreeNode* root) {
vector res;
traverse(root, 0, res);
return res;
}
4. 637 每层的平均值,易变体,迭代ok
易错需注意:有运算和大的加时,记得type:double、long,反正不能用int了,我这个方面意识薄弱
vector averageOfLevels(TreeNode* root) {
vector res;
queuemyq;
TreeNode* node;
if(root!=nullptr) myq.push(root);
while(!myq.empty()){
int size=myq.size();
long sum=0;
double avg=0;
for(int i=0;ileft!=nullptr) myq.push(node->left);
if(node->right!=nullptr) myq.push(node->right);
sum+=node->val;
}
avg=(double)sum/size;
res.push_back(avg);
}
return res;
}
递归会很复杂,对同层元素之间操作的(求平均值,找最大/小值,放入next)都不适合用recursion-dfs做,会非常复杂。下面是gpt写的,过了,我是懒得写了,复杂而且不适合
void averageOfLevels(TreeNode* node, int depth, vector& sums, vector& counts) {
if (node == nullptr) return;
if (depth >= sums.size()) {
sums.push_back(node->val);
counts.push_back(1);
} else {
sums[depth] += node->val;
counts[depth] += 1;
}
averageOfLevels(node->left, depth + 1, sums, counts);
averageOfLevels(node->right, depth + 1, sums, counts);
}
vector averageOfLevels(TreeNode* root) {
vector sums;
vector counts;
averageOfLevels(root, 0, sums, counts);
vector averages;
for (int i = 0; i < sums.size(); ++i) {
averages.push_back(static_cast(sums[i]) / counts[i]);
}
return averages;
}
5. 429 N叉树的层序遍历,易变体,递归懒得写了,下面是迭代,但思路都是该做左右的时候改成一个for loop做n个崽
vector> levelOrder(Node* root) {
vector> res;
queue myq;
Node* node;
if(root!=nullptr) myq.push(root);
while(!myq.empty()){
int size=myq.size();
vector vec;
for(int i=0;ival);
vector clist=node->children;
for(auto &ele:clist){
myq.push(ele);
}
}
res.push_back(vec);
}
return res;
}
6. 515.在每个树行中找最大值,和取每层最右像
我写的递归,但逻辑上讲不适合递归,虽然也是好写的
void order(int depth, vector &res, TreeNode* node){
if(node==nullptr) return;
// 当这一层还没有值时,将节点的值添加到结果中
if(res.size() == depth) res.push_back(node->val);
// 否则,更新这一层的最大值
else res[depth] = std::max(res[depth], node->val);
if(node->left!=nullptr) order(depth+1, res, node->left);
if(node->right!=nullptr) order(depth+1, res, node->right);
}
vector largestValues(TreeNode* root) {
vector res;
int depth=0;
order(depth, res, root);
return res;
}
代码随想录的迭代,就是基本迭代加了一点点取max
vector largestValues(TreeNode* root) {
queue que;
if (root != NULL) que.push(root);
vector result;
while (!que.empty()) {
int size = que.size();
int maxValue = INT_MIN; // 取每一层的最大值
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
maxValue = node->val > maxValue ? node->val : maxValue;
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
result.push_back(maxValue); // 把最大值放进数组
}
return result;
}
7.8. 116.填充每个节点的下一个右侧节点指针,117 II 两题没差
这个不完全算简单变体,我做的时候遇到点麻烦:原来是这么写的
修改正确后:
Node* connect(Node* root) {
queue myq;
Node* node;
Node* prev=nullptr;
if(root!=nullptr) myq.push(root);
while(!myq.empty()){
int size=myq.size();
for(int i=0;i0) prev->next=node;
if(node->left!=nullptr) myq.push(node->left);
if(node->right!=nullptr) myq.push(node->right);
prev=node;
}
node->next=nullptr;
}
return root;
}
这题也不适合递归做,所以没做递归
做深度,用recursion ,iteration都行,问题不大
9. 104 最大深度
递归我的
int get_depth(TreeNode* node){
if(node==nullptr) return 0;
int left_d=0; int right_d=0;
if(node->left!=nullptr) left_d=get_depth(node->left);
if(node->right!=nullptr) right_d=get_depth(node->right);
return std::max(left_d,right_d)+1;
}
int maxDepth(TreeNode* root) {
return get_depth(root);
}
void order(int depth, TreeNode * node, int &max){
if(node==nullptr) return;
max=std::max(max,depth);
if(node->left!=nullptr) order(depth+1,node->left,max);
if(node->right!=nullptr) order(depth+1,node->right,max);
}
int maxDepth(TreeNode* root) {
int depth=1;
int max=0;
order(depth, root, max);
return max;
}
递归简洁版
int maxDepth(TreeNode* root) {
if(root == nullptr)
return 0;
else
return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}
迭代(基础版迭代加个depth就行)
int maxDepth(TreeNode* root) {
if(root == nullptr)
return 0;
queue que;
que.push(root);
int depth = 0;
while(!que.empty()){
int size = que.size();
for(int i = 0; i < size; i++){
TreeNode* node = que.front();
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
depth++;
}
return depth;
}
10. 111 最小深度
我的递归(基础款不用动脑改)
void order(TreeNode * node, int &min, int depth){
if(node==nullptr){
min=0;
return;
}
if(node->left==nullptr && node->right==nullptr){
min=std::min(min,depth);
}
if(node->left!=nullptr) order(node->left,min,depth+1);
if(node->right!=nullptr) order(node->right,min,depth+1);
}
int minDepth(TreeNode* root) {
int depth=1;
int min=INT_MAX;
order(root, min, depth );
return min;
}
迭代gpt:走到第一个leaf node就可以结束啦!!会更有效率
int minDepth(TreeNode* root) {
if(root == nullptr)
return 0;
queue que;
que.push(root);
int depth = 0;
while(!que.empty()){
int size = que.size();
depth++;
for(int i = 0; i < size; i++){
TreeNode* node = que.front();
que.pop();
if(node->left == nullptr && node->right == nullptr)
return depth;
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return depth;
}
226.翻转二叉树
方法包括:
dfs recursion:前后就是套模板加swap,中序需要两次left中间夹swap
void order(TreeNode * node){
if(node==nullptr) return;
//这是很特殊的中序,swap后左右换了所以再一次左
if(node->left!=nullptr) order(node->left);
swap(node->left,node->right);
if(node->left!=nullptr) order(node->left);
//前序和后续就是普通:like this
//if(node->left!=nullptr) order(node->left);
//if(node->right!=nullptr) order(node->right);
//swap(node->left,node->right);
}
TreeNode* invertTree(TreeNode* root) {
order(root);
return root;
}
dfs iteration:直接套统一迭代的模板,加一句swap
TreeNode* invertTree(TreeNode* root) {
stack st;
if (root != NULL) st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != NULL) {
st.pop();
if (node->right) st.push(node->right); // 右
if (node->left) st.push(node->left); // 左
st.push(node); // 中
st.push(NULL);
} else {
st.pop();
node = st.top();
st.pop();
swap(node->left, node->right); // 节点处理逻辑
}
}
return root;
}
bfs iteration:套层序遍历的模板
TreeNode* invertTree(TreeNode* root) {
queue 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 对称二叉树2
第一次做想了好久
bool isSymmetric(TreeNode* root) {
queue myq1;
queue myq2;
if(root!=nullptr){
myq1.push(root);
myq2.push(root);
}
TreeNode *node1, *node2;
while(!(myq1.empty() ||myq2.empty())){
int size1=myq1.size();
int size2=myq2.size();
if(size1!=size2) return false;
for(int i=0;ival!=node2->val) return false;
if(node1->left!=nullptr){
if(node2->right==nullptr) return false;
myq1.push(node1->left);
}
if(node1->right!=nullptr){
if(node2->left==nullptr) return false;
myq1.push(node1->right);
}
if(node2->right!=nullptr){
if(node1->left==nullptr) return false;
myq2.push(node2->right);
}
if(node2->left!=nullptr){
if(node1->right==nullptr) return false;
myq2.push(node2->left);
}
}
}
if(!(myq1.empty()&&myq2.empty())) return false;
return true;
}
自己想的过于复杂,参考答案很简单的:
关键是:return compare(left->left,right->right)&&compare(left->right,right->left);
bool compare(TreeNode* left, TreeNode* right){
if(left==nullptr && right==nullptr) return true;
if(left==nullptr) return false;
if(right==nullptr) return false;
if(left->val!=right->val) return false;
return compare(left->left,right->right)&&compare(left->right,right->left);
}
bool isSymmetric(TreeNode* root) {
if(root==nullptr) return true;
return compare(root->left,root->right);
}