Binary Tree Zigzag Level Order Traversal

The more we do,the more we can do.

1. 题目:二叉树锯齿形层次遍历
Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).

For example:
Given binary tree [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
return its zigzag level order traversal as:
[
  [3],
  [20,9],
  [15,7]
]
2. 解析

本来看错题目以为就是简单的层次遍历,一个队列就可以解决问题。后来发现有个 锯齿形(zigzag) 。这样遍历每一层就可能有两个顺序,一个是 从左到右(ltr),另一个是 从右到左(rtl),整个的遍历顺序就是先ltr,再rtl,如此循环交替。

拿上面的例子看一下:

  • 当遍历顺序是rtl时,也就是第二层,我们最终要的顺序应该是 20->9,这里我们先把9插入队列,再插入20,然后每次从队尾取出元素,就是要求的顺序。

  • 当遍历顺序是ltr时,看看第三层,我们最终要的顺序应该是 15->7,这里我们先把7插入队列,再插入15,然后每次从队尾取出元素,就是要求的顺序。

可以比较一下:当 rtl 时,先插入的是左儿子,当 ltr 时,先插入的是右儿子。思路有了,直接写代码。C++ 代码如下:

3. 代码
#include <iostream>
#include <vector>

using namespace std;

typedef struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

void printResult(vector<vector<int>> res) {
    int size = res.size();
    for (int i = 0; i < size; ++i) {
        vector<int> item = res[i];
        for (int j = 0; j < item.size(); ++j) {
            cout << item[j] << " ";
        }
        cout << endl;
    }
}

/**
 * 1. 生成一个哨兵指针,始终指向某一层的第一个节点
 * 2. 每次将节点插入到一个队列末尾,当遍历到上一个哨兵的时候,表面这一层全部遍历结束
 * @param root
 * @return
 */
vector<vector<int>> zigzagLevelOrder(TreeNode *root) {

    vector<vector<int>> result;

    vector<vector<TreeNode *>> resultNodes;

    bool ltr = false;//true : 从左往右遍历.false : 从右往左遍历

    if (root == NULL) {
        return result;
    }
    TreeNode *layerEnd = root;//指向某一层队首的哨兵

    vector<TreeNode *> currentNodes;
    vector<TreeNode *> nextNodes;

    vector<int> next;

    currentNodes.push_back(root);

    resultNodes.push_back(currentNodes);

    while (!currentNodes.empty()) {

        //1. 每次都从队尾访问并取出,
        TreeNode *tmp;
        tmp = currentNodes.back();
        currentNodes.pop_back();

        //2. 插入到当前层的表示队列 next
        cout << tmp->val << endl;
        next.push_back(tmp->val);

        if (ltr) {
            //3. 如果是 ltr
            if (tmp->right != NULL) {
                nextNodes.push_back(tmp->right);
            }

            if (tmp->left != NULL) {
                nextNodes.push_back(tmp->left);
            }
        } else {
            //3. 如果是 rtl
            if (tmp->left != NULL) {
                nextNodes.push_back(tmp->left);
            }

            if (tmp->right != NULL) {
                nextNodes.push_back(tmp->right);
            }
        }

        //4. 如果遇到哨兵节点,表面此层遍历结束。
        if (tmp == layerEnd) {
            //存入结果
            result.push_back(next);
            resultNodes.push_back(nextNodes);

            //注意这里是结束条件
            if (nextNodes.empty()) {
                break;
            }

            //哨兵放在队首
            layerEnd = nextNodes.front();

            //将下一层加入缓存遍历
            currentNodes.clear();
            currentNodes.insert(currentNodes.end(), nextNodes.begin(), nextNodes.end());
            
            //注意清空
            nextNodes.clear();
            next.clear();
            ltr = !ltr;
        }

    }
    printResult(result);
    return result;

}
4. 测试
int main() {
    TreeNode *node_a = new TreeNode(3);
    TreeNode *node_b = new TreeNode(9);
    TreeNode *node_c = new TreeNode(20);
    TreeNode *node_d = new TreeNode(15);
    TreeNode *node_e = new TreeNode(7);

    node_a->left = node_b;
    node_a->right = node_c;
    node_c->left = node_d;
    node_c->right = node_e;

    zigzagLevelOrder(node_a);
    return 0;
}

输出:

3 
20 9 
15 7 

正确。


THE END.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值