代码随想录算法训练营Day15|二叉树的层序遍历、226.翻转二叉树、101.对称二叉树

一、二叉树的层序遍历

  1. 102 二叉树的层序遍历

题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/

思路:借助一个队列,先入队根节点,然后每出队一个节点,就将它的的left和right分别入队。

代码:

var levelOrder = function(root) {
    if (!root) {
        return [];
    }
    var result = [];
    var queue = [];
    queue.push(root);
    while (queue.length !== 0) {
        // 需要记一下这个时候队列的长度,就是这一层应该有几个节点
        var size = queue.length;
        var level = [];
        for (let i=0; i

  1. 107 二叉树的层序遍历II

题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/

思路:先层序遍历,然后反转就好了

代码:

var levelOrderBottom = function(root) {
    if (!root) {
        return [];
    }
    var result = [];
    var queue = [];
    queue.push(root);
    while (queue.length !== 0) {
        // 需要记一下这个时候队列的长度,就是这一层应该有几个节点
        var size = queue.length;
        var level = [];
        for (let i=0; i

  1. 199 二叉树的右视图

题目链接:https://leetcode.cn/problems/binary-tree-right-side-view/

思路:层序遍历,但只有遍历到一层的最后一个时才加入result

代码:

var rightSideView = function(root) {
    if (!root) {
        return [];
    }
    var queue = [];
    queue.push(root);
    var result = [];
    while (queue.length !== 0) {
        var size = queue.length;
        for (let i=size; i>0; i--) {
            var cur = queue.shift();
            if (i == 1) {
                result.push(cur.val);
            }
            if (cur.left) {
                queue.push(cur.left);
            }
            if (cur.right) {
                queue.push(cur.right);
            }
        }
    }
    return result;
};

  1. 637 二叉树的层平均值

题目链接:https://leetcode.cn/problems/average-of-levels-in-binary-tree/

代码:

var averageOfLevels = function(root) {
    if (!root) {
        return [];
    }
    var result = [];
    var queue = [];
    queue.push(root);
    while (queue.length !== 0) {
        var size = queue.length;
        var sum = 0;
        for (let i=0; i

  1. 429 N叉树的层序遍历

题目链接:https://leetcode.cn/problems/n-ary-tree-level-order-traversal/

代码:

var levelOrder = function(root) {
    if (!root) {
        return [];
    }
    var result = [];
    var queue = [];
    var size = 1;
    queue.push(root);
    while (queue.length) {
        var list = [];
        for (let i=size; i>0; i--) {
            var node = queue.shift();
            list.push(node.val);
            for (const child of node.children) {
                queue.push(child);
            }
        }
        size = queue.length;
        result.push(list);
    }
    return result;
};

  1. 515 在每个树行中找最大值

题目链接:https://leetcode.cn/problems/find-largest-value-in-each-tree-row/

代码:

var largestValues = function(root) {
    if (!root) {
        return [];
    }
    var result = [];
    var queue = [];
    queue.push(root);
    while (queue.length !== 0) {
        var size = queue.length;
        var max = Number.MIN_VALUE;
        for (let i=0; i max ? cur.val : max;
            if (cur.left) {
                queue.push(cur.left);
            }
            if (cur.right) {
                queue.push(cur.right);
            }
        }
        result.push(max);
    }
    return result;
};

  1. 116 填充每个节点的下一个右侧节点指针

题目链接:https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/

代码:

var connect = function(root) {
    if (!root) {
        return root;
    }
    var size = 1;
    var queue = [];
    queue.push(root);
    while (queue.length) {
        for (var i=size; i>0; i--) {
            var node = queue.shift();
            // 如果是这层最后一个节点,则让其指向null
            if (i === 1) {
                node.next = null;
            }
            // 如果不是的话,让其指向下一个节点,即队列口的元素
            else {
                node.next = queue[0];
            }
            if (node.left) {
                queue.push(node.left);
            }
            if (node.right) {
                queue.push(node.right);
            }
        }
        size = queue.length;
    }
    return root;
};

  1. 117 填充每个节点的下一个右侧节点指针II

题目链接:https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/

代码:和上一题完全一样,本质上是不是完美二叉树对求解没有影响。

  1. 104 二叉树的最大深度

题目链接:https://leetcode.cn/problems/maximum-depth-of-binary-tree/

代码:

var maxDepth = function(root) {
    if (!root) {
        return 0;
    }
    var depth = 0;
    var queue = [];
    var size = 1;
    queue.push(root);
    while (queue.length) {
        for (let i=size; i>0; i--) {
            var node = queue.shift();
            if (node.left) {
                queue.push(node.left);
            }
            if (node.right) {
                queue.push(node.right);
            }
        }
        depth += 1;
        size = queue.length;
    }
    return depth;
};

  1. 111 二叉树的最小深度

题目链接:https://leetcode.cn/problems/minimum-depth-of-binary-tree/

代码:

var minDepth = function(root) {
    if (!root) {
        return 0;
    }
    var queue = []
    var size = 1;
    var depth = 1;
    queue.push(root);
    while (queue.length) {
        for (let i=size; i>0; i--) {
            var node = queue.shift();
            if (!node.left && !node.right) {
                return depth;
            }
            if (node.left) {
                queue.push(node.left);
            }
            if (node.right) {
                queue.push(node.right);
            }
        }
        size = queue.length;
        depth += 1;
    }
    return depth;
};

二、226 翻转二叉树

  1. 题目链接:https://leetcode.cn/problems/invert-binary-tree/

  1. 思路:前序遍历,递归版本。这道题用前序和后序都比较方便,不能用中序。

递归三部曲:首先确定递归函数的返回值和参数,这个返回值就是root,参数也是root;其次是终止条件,遇到空节点,就返回它本身,即null;最后看处理逻辑,是应该交换目前节点的左右子树,然后对它们再依次翻转。

  1. 代码:

var invertTree = function(root) {
    // 递归法,前序遍历
    if (!root) {
        return root;
    }
    // 中
    [root.left, root.right] = [root.right, root.left];
    // 左
    invertTree(root.left);
    // 右
    invertTree(root.right);
    return root;
};
  1. 中序遍历为什么不行:中序遍历是左中右,先将左子树翻转完了,然后交换左右子树,再处理右子树,相当于是一直在处理同一边的子树。

三、101 对称二叉树

  1. 题目链接:https://leetcode.cn/problems/symmetric-tree/

  1. 思路:只能使用后序遍历,左右中,因为我们要不断地收集左右孩子的信息返回给上一个节点,才能知道以左节点为根节点的树和以右节点为根节点的树是否是可以相互翻转的。

  1. 代码:

var isSymmetric = function(root) {
    // 判断左右子树是否可以互相翻转,这里传入的是根节点的左右子树的头结点
    var compare = function (left, right) {
        if (left && !right) {
            return false;
        }
        else if (!left && right) {
            return false;
        }
        else if (!left && !right) {
            return true;
        }
        else if (left.val != right.val) {
            return false;
        }
        // 外侧节点,左节点的左孩子和右节点的右孩子
        var outside = compare(left.left, right.right);
        // 内侧节点,左节点的右孩子和右节点的左孩子
        var inside = compare(left.right, right.left);
        // 这里可以看出,左子树的遍历顺序是左右中,而右子树是右左中
        return inside && outside;
    }
    return compare(root.left, root.right)
};

  1. 100 相同的树

题目链接:https://leetcode.cn/problems/same-tree/

思路:递归方法比较左子树和右子树是否相等,这次相当于是用了前序遍历

代码:

var isSameTree = function(p, q) {
    if (!p && !q) {
        return true;
    }
    else if (!p || !q) {
        return false;
    }
    else if (p.val !== q.val) {
        return false;
    }
    // 相当于中左右,先判断了p和q的值相等,然后分别判断左右子树
    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
};

  1. 572 另一个树的子树

题目链接:https://leetcode.cn/problems/subtree-of-another-tree/

代码:

var isSubtree = function(root, subRoot) {
    //此题也类似判断两个二叉树是否相等
    const compare = function(left,right){
        if(!left && !right){
            return true;
        }
        else if(left!==null&&right===null||left===null&&right!==null||left.val!==right.val){
            return false;
        }
        let leftSide = compare(left.left,right.left);
        let rightSide = compare(left.right,right.right);
        let isSame = leftSide&&rightSide;
        return isSame;
    }
   if(root===null){
       return false
   }
   if(compare(root,subRoot)){
       return true;
   }
   return isSubtree(root.left,subRoot)||isSubtree(root.right,subRoot);
};

今日学习时间:4h左右

总结:层序遍历比较简单,但是后面两道题还没有做透,对称二叉树明天补。

更新:翻转二叉树使用的是前序遍历或后序遍历,而对称二叉树使用的是中序遍历,严格来讲左子树是左右中,右子树是右左中。下次再刷的时候需要注意226、101和572。

你可能感兴趣的:(算法训练营,javascript,算法,数据结构,leetcode)