# 0103. 二叉树的锯齿形层次遍历 ## 题目地址(103. 二叉树的锯齿形层次遍历) <https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/> ## 题目描述 和leetcode 102 基本是一样的,思路是完全一样的。 ``` <pre class="calibre18">``` 给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 例如: 给定二叉树 [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回锯齿形层次遍历如下: [ [3], [20,9], [15,7] ] ``` ``` ## 前置知识 - 队列 ## 公司 - 阿里 - 腾讯 - 百度 - 字节 ## 思路 这道题可以借助`队列`实现,首先把root入队,然后入队一个特殊元素Null(来表示每层的结束)。 然后就是while(queue.length), 每次处理一个节点,都将其子节点(在这里是left和right)放到队列中。 然后不断的出队, 如果出队的是null,则表式这一层已经结束了,我们就继续push一个null。 ## 关键点解析 - 队列 - 队列中用Null(一个特殊元素)来划分每层 - 树的基本操作- 遍历 - 层次遍历(BFS) ## 代码 - 语言支持:JS,C++ JavaScript Code: ``` <pre class="calibre18">``` <span class="hljs-title">/** * @param {TreeNode} root * @return {number[][]} */</span> <span class="hljs-keyword">var</span> zigzagLevelOrder = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">root</span>) </span>{ <span class="hljs-keyword">if</span> (!root) <span class="hljs-keyword">return</span> []; <span class="hljs-keyword">const</span> items = []; <span class="hljs-keyword">let</span> isOdd = <span class="hljs-params">true</span>; <span class="hljs-keyword">let</span> levelNodes = []; <span class="hljs-keyword">const</span> queue = [root, <span class="hljs-params">null</span>]; <span class="hljs-keyword">while</span>(queue.length > <span class="hljs-params">0</span>) { <span class="hljs-keyword">const</span> t = queue.shift(); <span class="hljs-keyword">if</span> (t) { levelNodes.push(t.val) <span class="hljs-keyword">if</span> (t.left) { queue.push(t.left) } <span class="hljs-keyword">if</span> (t.right) { queue.push(t.right) } } <span class="hljs-keyword">else</span> { <span class="hljs-keyword">if</span> (!isOdd) { levelNodes = levelNodes.reverse(); } items.push(levelNodes) levelNodes = []; isOdd = !isOdd; <span class="hljs-keyword">if</span> (queue.length > <span class="hljs-params">0</span>) { queue.push(<span class="hljs-params">null</span>); } } } <span class="hljs-keyword">return</span> items }; ``` ``` C++ Code: ``` <pre class="calibre18">``` <span class="hljs-title">/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */</span> <span class="hljs-keyword">class</span> Solution { <span class="hljs-keyword">public</span>: <span class="hljs-params">vector</span><<span class="hljs-params">vector</span><<span class="hljs-keyword">int</span>>> zigzagLevelOrder(TreeNode* root) { <span class="hljs-keyword">auto</span> ret = <span class="hljs-params">vector</span><<span class="hljs-params">vector</span><<span class="hljs-keyword">int</span>>>(); <span class="hljs-keyword">if</span> (root == <span class="hljs-params">nullptr</span>) <span class="hljs-keyword">return</span> ret; <span class="hljs-keyword">auto</span> <span class="hljs-params">queue</span> = <span class="hljs-params">vector</span><<span class="hljs-keyword">const</span> TreeNode*>{root}; <span class="hljs-keyword">auto</span> isOdd = <span class="hljs-params">true</span>; <span class="hljs-keyword">while</span> (!<span class="hljs-params">queue</span>.empty()) { <span class="hljs-keyword">auto</span> sz = <span class="hljs-params">queue</span>.size(); <span class="hljs-keyword">auto</span> level = <span class="hljs-params">vector</span><<span class="hljs-keyword">int</span>>(); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> i = <span class="hljs-params">0</span>; i < sz; ++i) { <span class="hljs-keyword">auto</span> n = <span class="hljs-params">queue</span>.front(); <span class="hljs-params">queue</span>.erase(<span class="hljs-params">queue</span>.begin()); <span class="hljs-keyword">if</span> (isOdd) level.push_back(n->val); <span class="hljs-keyword">else</span> level.insert(level.begin(), n->val); <span class="hljs-keyword">if</span> (n->left != <span class="hljs-params">nullptr</span>) <span class="hljs-params">queue</span>.push_back(n->left); <span class="hljs-keyword">if</span> (n->right != <span class="hljs-params">nullptr</span>) <span class="hljs-params">queue</span>.push_back(n->right); } isOdd = !isOdd; ret.push_back(level); } <span class="hljs-keyword">return</span> ret; } }; ``` ``` ## 拓展 由于二叉树是递归结构,因此,可以采用递归的方式来处理。在递归时需要保留当前的层次信息(从0开始),作为参数传递给下一次递归调用。 ### 描述 1. 当前层次为偶数时,将当前节点放到当前层的结果数组尾部 2. 当前层次为奇数时,将当前节点放到当前层的结果数组头部 3. 递归对左子树进行之字形遍历,层数参数为当前层数+1 4. 递归对右子树进行之字形遍历,层数参数为当前层数+1 ### C++实现 ``` <pre class="calibre18">``` <span class="hljs-keyword">class</span> Solution { <span class="hljs-keyword">public</span>: <span class="hljs-params">vector</span><<span class="hljs-params">vector</span><<span class="hljs-keyword">int</span>>> zigzagLevelOrder(TreeNode* root) { <span class="hljs-keyword">auto</span> ret = <span class="hljs-params">vector</span><<span class="hljs-params">vector</span><<span class="hljs-keyword">int</span>>>(); zigzagLevelOrder(root, <span class="hljs-params">0</span>, ret); <span class="hljs-keyword">return</span> ret; } <span class="hljs-keyword">private</span>: <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">zigzagLevelOrder</span><span class="hljs-params">(<span class="hljs-keyword">const</span> TreeNode* root, <span class="hljs-keyword">int</span> level, <span class="hljs-params">vector</span><<span class="hljs-params">vector</span><<span class="hljs-keyword">int</span>>>& ret)</span> </span>{ <span class="hljs-keyword">if</span> (root == <span class="hljs-params">nullptr</span> || level < <span class="hljs-params">0</span>) <span class="hljs-keyword">return</span>; <span class="hljs-keyword">if</span> (ret.size() <= level) { ret.push_back(<span class="hljs-params">vector</span><<span class="hljs-keyword">int</span>>()); } <span class="hljs-keyword">if</span> (level % <span class="hljs-params">2</span> == <span class="hljs-params">0</span>) ret[level].push_back(root->val); <span class="hljs-keyword">else</span> ret[level].insert(ret[level].begin(), root->val); zigzagLevelOrder(root->left, level + <span class="hljs-params">1</span>, ret); zigzagLevelOrder(root->right, level + <span class="hljs-params">1</span>, ret); } }; ``` ``` ## 相关题目 - [102.binary-tree-level-order-traversal](102.binary-tree-level-order-traversal.html) - [104.maximum-depth-of-binary-tree](104.maximum-depth-of-binary-tree.html)