leetcode:103. 二叉树的锯齿形层序遍历

题目来源

题目描述

在这里插入图片描述

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {

    }
};

题目解析

这道题是leetcode:102.Binary Tree Level Order Traversal 二叉树层序遍历的变形,不同之处在于一行是从左到右遍历,下一行是从右到左遍历,交叉往返的之字形的层序遍历

在这里插入图片描述

bfs

最简单直接的方法就是利用层次遍历,并使用一个变量cnt来统计当前的层数(从0开始),将所有的奇数层的结点值进行翻转一下即可

如下:

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        if(root == nullptr){
            return {};
        }
        std::vector<std::vector<int>>res;
        std::queue<TreeNode *> q{{root}};
        int cnt = 0;
        while (!q.empty()){
            std::vector<int> oneLevel;
            for (int i = q.size(); i > 0; --i) {
                TreeNode *t = q.front(); q.pop();
                oneLevel.push_back(t->val);
                if(t->left){
                    q.push(t->left);
                }
                if(t->right){
                    q.push(t->right);
                }
            }
            if(cnt % 2 == 1){
                std::reverse(oneLevel.begin(), oneLevel.end());
            }
            res.push_back(oneLevel);
            ++cnt;
        }
        return res;
    }
};

在这里插入图片描述

bfs

  • 问题是反转数组太耗时了,如果能够直接计算出每个节点值在数组中的坐标,就可以直接进行更新了。
  • 由于每层的节点数是知道的,也就是队列的元素个数,所以可以直接初始化数组的大小。
  • 此时可以使用一个变量leftToRight来标记顺序,初始时是true。
    • 当变量值为true时,每次加入数组的位置就是i本身
    • 如果值为false时,则加入到size-1-i位置上。
  • 这样就相当于反转了数组
  • 每层遍历完成之后,需要翻转 leftToRight 变量,同时不要忘了将 oneLevel 加入结果 res
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        if (!root) return {};
        vector<vector<int>> res;
        queue<TreeNode*> q{{root}};
        bool leftToRight = true;
        while (!q.empty()) {
            int size = q.size();
            vector<int> oneLevel(size);
            for (int i = 0; i < size; ++i) {
                TreeNode *t = q.front(); q.pop();
                int idx = leftToRight ? i : (size - 1 - i);
                oneLevel[idx] = t->val;
                if (t->left) q.push(t->left);
                if (t->right) q.push(t->right);
            }
            leftToRight = !leftToRight;
            res.push_back(oneLevel);
        }
        return res;
    }
};

递归

这里可以看成是一个先序遍历。递归函数需要用一个变量level来记录当前的深度。

  • 由于level是从0开始的,假如结果res的大小等于level,就需要在结果res中新加一个空集,这样可以保证res[level]不会越界。
  • 取出res[level]之后,判断level的奇偶,如果为偶数,就将node->val加入到onelevel的末尾,如果是奇数,就加到onelevel的开头。然后分别对 node 的左右子结点调用递归函数,此时要传入 level+1 即可
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> res;
        helper(root, 0, res);
        return res;
    }
    void helper(TreeNode* node, int level, vector<vector<int>>& res) {
        if (!node) return;
        if (res.size() <= level) {
            res.push_back({});
        }
        vector<int> &oneLevel = res[level];
        if (level % 2 == 0) oneLevel.push_back(node->val);
        else oneLevel.insert(oneLevel.begin(), node->val);
        helper(node->left, level + 1, res);
        helper(node->right, level + 1, res);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值