AcWing 45. 之字形打印二叉树(双栈法+reverse方法)

1.双栈法

根据经验,我们可以发现这道题需要对层次遍历的模板进行一定的改动。如果我们将根节点所在层定义为第0层,可以发现凡是偶数层都是从左往右打印,而奇数层却恰好相反。考虑到下一层与上一层节点的关系以及他们的相反输出次序,可以试着引入栈来进行反向输出的操作。那么问题来了,要怎么去设计对栈的控制呢?

这里的方案是引入两个栈,一个负责偶数层节点,记作stack0,另一个负责奇数层的,记作stack1。偶数层节点出栈前将其孩子压入stack1,次序是先左后右。奇数层节点出栈前将其孩子压入stack0,次序是先右后左。当当前负责出栈的栈为空时说明当前层已经完全遍历,需要换行。此时只要换做另一个栈来重复以上操作即可。

我们以样例中的二叉树为例。首先,8压入了stack0,出栈前将12,2压入了stack1,8出栈后stack0变空,切换到stack1进行操作;stack1中2先出栈,出站前将4,6压入stack0,然后12出栈,stack1变空,切换到stack0进行操作;stack0再将6,4出栈。程序结束。

具体代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> printFromTopToBottom(TreeNode* root) {
        vector<vector<int>> ans;
        if(!root) return ans;
        stack<TreeNode *> stack[2];
        int state = 0; //state为0表示从左往右打印,为1则从右往左打印
        stack[state].push(root);
        vector<int> temp;
        while(!stack[state].empty()){
            TreeNode *p = stack[state].top();
            stack[state].pop();
            temp.push_back(p -> val);
            if(!state){ //偶数层节点的孩子入栈次序为先左后右
                if(p -> left) stack[(state + 1) % 2].push(p -> left);
                if(p -> right) stack[(state + 1) % 2].push(p -> right);
            }
            else{ //奇数层的孩子入栈次序为先右后左
                if(p -> right) stack[(state + 1) % 2].push(p -> right);
                if(p -> left) stack[(state + 1) % 2].push(p -> left);
            }
            if(stack[state].empty()){ //当前栈为空说明需要换行
                ans.push_back(temp);
                temp.clear();
                state = (state + 1) % 2; //改变当前层的奇偶性状态
            }
        }
        return ans;
    }
};

2.reverse方法

这种方法实际上是对双栈法的简化。这里不再需要设置两个栈,只是在当前层遍历完毕后判断层数的奇偶性。如果是奇数层则用reverse()反转向量并保存,否则不需反转直接保存即可。

关于层数判断的方法,这里采用的是标记法(请参考我的另一篇博文)。

具体代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> printFromTopToBottom(TreeNode* root) {
        vector<vector<int>> ans;
        if(!root) return ans;
        queue<TreeNode *> q;
        q.push(root);
        q.push(NULL);
        int state = 0; //state为0表示从左往右打印,为1则从右往左打印
        vector<int> temp;
        while(!q.empty()){
            TreeNode *p = q.front();
            q.pop();
            if(p){
                temp.push_back(p -> val);
                if(p -> left) q.push(p -> left);
                if(p -> right) q.push(p -> right);
            }
            else{ //节点为空说明需要换行
                if(state) reverse(temp.begin(), temp.end()); //根据层数奇偶性判断是否要反转
                ans.push_back(temp);
                state = (state + 1) % 2; //改变当前层的奇偶性状态
                temp.clear();
                if(!q.empty()) q.push(NULL);
            }
        }
        return ans;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值