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;
}
};