面试题32

题目地址:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/

题目描述

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

题目示例

例如:
给定二叉树: [3,9,20,null,null,15,7],

     3
   /   
   9    20
    /   
     15  7
返回其层次遍历结果:

[
[3],
[9,20],
[15,7]
]

解题思路

思路1(BFS,即普通队列queue):利用bool值flag来区分奇偶层,当flag=true时,从左往右遍历,否则,从右往左遍历,BFS中我们默认从左往右遍历,那么如何从右往左如何遍历呢?我们只需要将存储该层节点的数组arr翻转一下就可以了。

思路2(双端队列deque):此题与第32题其它两个变版不一样,涉及到了奇偶层不同的遍历方式,观察题目可以发现,二叉树的奇数层从左往右打印节点,而偶数层则从右往左打印节点,我们可以利用双端队列deque解决此问题。

思路3(队列+栈):我们使用队列实现二叉树的遍历,然后使用栈翻转每一层节点。

思路4(栈+栈):我们知道双栈可以实现队列,所以利用栈的后进先出特点解决此问题。其中,两个栈分别存放奇数层、偶数层节点,弹栈的时候,依次将栈顶节点的子节点压入相反的栈,直到两个栈均为空为止。

程序源码

思路1:普通队列queue改进

/**
 * 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>> levelOrder(TreeNode* root) {
        if(root == nullptr) return {};
        vector<vector<int>> res;
        
        queue<TreeNode* > q;
        q.push(root);
        bool flag = true; //默认从左往右遍历,即flag=true,当flag=false时,从右往左遍历
        while(!q.empty())
        {
            vector<int> arr;
            int level_node = q.size();
            for(int i = 0; i < level_node; i++)
            {
                TreeNode* node = q.front();
                arr.push_back(node->val);
                q.pop();
                if(node->left != nullptr) q.push(node->left);
                if(node->right != nullptr) q.push(node->right);
            }
            if(flag == false) reverse(arr.begin(), arr.end()); //奇数层,翻转节点,从右往左遍历
            flag = !flag; //更新flag值,遍历下一层节点
            res.push_back(arr);
        }
        return res;
    }
};

 思路2:双端队列deque

/**
 * 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>> levelOrder(TreeNode* root) {
        if(root == nullptr) return {};
        vector<vector<int>> res;
        deque<TreeNode* > q;
        q.push_back(root);
        bool flag = true; //默认从左往右遍历,即flag=true,当flag=false时,从右往左遍历
        while(!q.empty())
        {
            vector<int> arr;
            int level_node = q.size();
            TreeNode* node;
            for(int i = 0; i < level_node; i++)
            {
                if(flag == true)
                {
                    node = q.front(); //从左往右遍历,即从每层第一个节点取
                    arr.push_back(node->val); //存放该层节点
                    q.pop_front(); //从左边取,右边放
                    if(node->left != nullptr) q.push_back(node->left); //放左边节点
                    if(node->right != nullptr) q.push_back(node->right); //放右边节点
                }
                else
                {
                    node = q.back(); //从右往左遍历,即从每层最后一个节点取
                    arr.push_back(node->val); //存放该层节点
                    q.pop_back(); //从右边取,左边放
                    if(node->right != nullptr) q.push_front(node->right); //放右边节点
                    if(node->left != nullptr) q.push_front(node->left); //放左边节点
                }
            }
            flag = !flag; //更新flag值,遍历下一层节点
            res.push_back(arr);
        }
        return res;
    }
};

思路3:”队列+栈“双剑合璧

/**
 * 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>> levelOrder(TreeNode* root) {
        if(root == nullptr) return {};
        vector<vector<int>> res;
        queue<TreeNode* > q;
        stack<TreeNode* > s;
        q.push(root);
        bool flag = true; //默认从左往右遍历,即flag=true,当flag=false时,从右往左遍历
        while(!q.empty())
        {
            vector<int> arr;
            int level_node = q.size();
            for(int i = 0; i < level_node; i++)
            {
                TreeNode* node = q.front();
                arr.push_back(node->val);
                q.pop();
                if(flag == true) //偶数层从左往右遍历
                {
                    if(node->left != nullptr) s.push(node->left);
                    if(node->right != nullptr) s.push(node->right);
                }
                else //奇数层从右往左遍历
                {
                    if(node->right != nullptr) s.push(node->right);
                    if(node->left != nullptr) s.push(node->left);
                }
            }
            while(!s.empty())
            {
                q.push(s.top()); //翻转加入队列q
                s.pop();
            }
            flag = !flag; //更新flag值,遍历下一层节点
            res.push_back(arr);
            arr.clear(); //清空数组中存放的节点
        }
        return res;
    }
};

思路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>> levelOrder(TreeNode* root) {
        if(root == nullptr) return {};
        vector<vector<int>> res;
        stack<TreeNode* > s1; //存放奇数层节点
        stack<TreeNode* > s2; //存放偶数层节点
        s1.push(root);
        bool flag = true; //默认从左往右遍历,即flag=true,当flag=false时,从右往左遍历
        while(!s1.empty() || !s2.empty())
        {
            vector<int> arr;
            if(flag == true) //奇数层
            {
                while(!s1.empty()) //清空栈s1,依次将节点压入栈s2(先左后右)
                {
                    TreeNode* node = s1.top();
                    arr.push_back(node->val);
                    s1.pop();
                    if(node->left != nullptr) s2.push(node->left);
                    if(node->right != nullptr) s2.push(node->right);
                }
            }
            else //偶数层
            {
                while(!s2.empty()) //清空栈s2,依次将节点压入栈s1(先右后左)
                {
                    TreeNode* node = s2.top();
                    arr.push_back(node->val);
                    s2.pop();
                    if(node->right != nullptr) s1.push(node->right);
                    if(node->left != nullptr) s1.push(node->left);
                }
            }
            flag = !flag; //更新flag值,遍历下一层节点
            res.push_back(arr);
        }
        return res;
    }
};
----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
原文地址:https://www.cnblogs.com/wzw0625/p/12879428.html