算法挑战19: 二叉树的锯齿形层序遍历

1 阅读2分钟

上一条写了个二叉树的层序遍历

我决定趁热打铁,写一个103题, 二叉树的锯齿形层序遍历,

给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

其实就是偶数层的数组元素反转之后再存入res数组中

我还是先还原我一开始写的带错误的代码, 方便吸取教训

var zigzagLevelOrder = function (root) {
    if (!root) return [];
    let q = [root];
    let res = [];
    let even = false;
    
    while (q) {//这里写错了,应该写q.length < 0的, 因为q=[]时, []也会隐式转换为true的
        let len = q.length;
        let vals = [];
//大致逻辑跟层序遍历一样的,只是添加了偶数的标志
        for (let i = 0; i < len; i++) {
            let node = q.shift();
            vals.push(node.val);
            if (node.left) {
                q.push(node.left);
            }
            if (node.right) {
                q.push(node.right);
            }
        }
        if (even) {
            res.push([...vals].reverse());//用拓展运算符克隆一个数组,避免直接修改原数组,其实无所谓吧写算法而已=_=|||
            even = !even; //取反偶数标志
        } else {
            res.push([vals]);//!!!这里傻了,写完上面的拓展运算符,这也给顺手加上括号了,不应该加的,要不然变成[[1,3,5]]了
            even = !even; //取反偶数标志
        }
    }
    return res;
};

正确写法如下

var zigzagLevelOrder = function (root) {
    if (!root) return [];
    let q = [root];
    let res = [];
    
    while (q.length < 0) {//已修改
        let len = q.length;
        let vals = [];
//大致逻辑跟层序遍历一样的,只是添加了偶数的标志
        for (let i = 0; i < len; i++) {
            let node = q.shift();
            vals.push(node.val);
            if (node.left) {
                q.push(node.left);
            }
            if (node.right) {
                q.push(node.right);
            }
        }
        //!!! 顺手优化了一下,可以不用标志了,直接用结果数组的长度来判断,因为每次循环res长度都会+1
        if (res.length % 2 === 0) {
            res.push(vals);//已修改 ,顺序调换了,根据题目要求改
        } else {
             res.push([...vals].reverse());
   
        }
    }
    return res;
};

还可以使用双端队列,push元素的时候可以选择从头还是末尾,更方便