题目简述
给定二叉树的根节点,打印二叉树的每一层,奇数层正序,偶数层逆序。
算法一(栈):
时间复杂度:O(N)
思路:
根据栈先进后出的特性,开两个栈,L 栈负责正序,R 栈负责逆序。
1. L栈中取左右儿子时按先左后右顺序存入R栈。
2. R栈中取左右儿子时按先右后左顺序存入L栈。
例如:{8,6,10,5,7,9,11,12,13,14,15,16,17,18,19}
(1) L={ 8 } R={ } 取出 : 8
(2) L={ } R={6,10} 取出 : 10,6
(3) L={11,9,7,5} R={ }; 取出 : 5,7,9,11
(4) L={ } R={12,13,14,15,16,17,18,19} 取出: 19,18,17,16,15,14,13,12
代码:
class Solution { public: vector<vector<int> > Print(TreeNode* pRoot) { stack<TreeNode*> l; stack<TreeNode*> r; vector<vector<int> > ans; if(pRoot) l.push(pRoot); while(l.size()||r.size()) { int lenL=l.size(); int lenR=r.size(); vector<int> res; //两个for只能进去一个 for(int i=0;i<lenL;i++){ //正序 auto root=l.top(); l.pop(); res.push_back(root->val); if(root->left) r.push(root->left); //先左后右 if(root->right) r.push(root->right); } for(int i=0;i<lenR;i++){//倒序 auto root=r.top(); r.pop(); res.push_back(root->val); if(root->right) l.push(root->right); //先右后左 if(root->left) l.push(root->left); } ans.push_back(res); } return ans; } };
算法二(队列):
时间复杂度:O(N)
思路:
1、 对于每层先正常存入vector中,然后判断该层是否需要翻转。
2、 存入操作:
(1) 先记录目前队列元素的个数size,这么多为树的同一层。
(2) 由于队列取出是从队首取,而插入是在队尾。那么我们取队首元素时,不断在队尾插入左右儿子,队列的顺序不变。
(3) 当我们取完前size时该层清空,队列此时为下一层的节点。
3、 判断操作:
由于是正序和逆序是交错的,所以我们直接利用mark的奇偶性即可,每层操作时都对mark++即可。
图解:
代码:
class Solution { public: vector<vector<int> > Print(TreeNode* pRoot) { queue<TreeNode*> q; vector<vector<int> > ans; if(pRoot) q.push(pRoot); int mark=0; while(q.size()) { mark++; int len=q.size(); vector<int> res; for(int i=0;i<len;i++){ //将该层存入 auto root=q.front(); q.pop(); if(root->left) q.push(root->left); if(root->right) q.push(root->right); res.push_back(root->val); } if(mark%2==0) reverse(res.begin(),res.end()); //将数组翻转 ans.push_back(res); } return ans; } };