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

 二叉树层序遍历

题目链接:二叉树层序遍历

文档讲解:代码随想录/二叉树层序遍历

视频讲解:视频讲解-二叉树层序遍历

状态:已完成(1遍)

解题过程 

看到题目的第一想法

 层序遍历我主要是怎么将队列和一层一层的遍历联系到一块想不出来,直接看讲解吧。

看完代码随想录之后的想法 

关键在于,每一层的for循环次数是固定的,而在遍历一层中节点的时候就把他们的左右子节点加入到queue中。

看完讲解手搓一版代码如下:

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function (root) {
    if (root == null) return [];
    else {
        let ans = [], queue = [];
        queue.push(root);
        while (queue.length != 0) {
            let len = queue.length;//当前层应该遍历的次数,下面for循环要用
            let smallAns = [];//每一层放进答案里的小数组
            for (let i = 0; i < len; i++) {
                let node = queue.shift();//队列头拿一个出来
                smallAns.push(node.val);
                // 存放当前层下一层的节点
                node.left && queue.push(node.left);
                node.right && queue.push(node.right);
            }
            ans.push(smallAns);
        }
        return ans;
    }
};

提交没有问题,这道题做完了可以用同样的方法继续做 107、199、104、111,解题思路完全一样,只是返回的东西以及处理的过程不太相同。

总结

层序遍历和数组的结合十分精妙,做完这道题还可以看一下层序遍历的其他题目,详情在文字讲解中。


 226.翻转二叉树

题目链接:226.翻转二叉树

文档讲解:代码随想录/翻转二叉树

视频讲解:视频讲解-翻转二叉树

状态:已完成(1遍)

解题过程  

看到题目的第一想法

这道题用层序遍历,在遍历到每一层的节点时,都将这个节点的左右子节点给相互交换,这样应该是可行的。

手搓一版如下:

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var invertTree = function(root) {
    if(root == null)return root;
    else{
        let ans = [],queue = [];
        queue.push(root);
        while(queue.length!=0){
            let len = queue.length;
            for(let i =0;i<len;i++){
                let node = queue.shift();
                [node.left,node.right]=[node.right,node.left];
                node.left && queue.push(node.left);
                node.right && queue.push(node.right);
                ans.push(node);
            }
        }
        return root;
    }
};

提交直接成功,芜湖,不枉我做完第一题之后又做了三四道同类型。 

 看完代码随想录之后的想法 

确实除了层序遍历之外还有前序遍历和后序遍历的方法,要简单不少。

讲解代码如下:

var invertTree = function(root) {
    // 终止条件
    if (!root) {
        return null;
    }
    // 交换左右节点
    const rightNode = root.right;
    root.right = invertTree(root.left);
    root.left = invertTree(rightNode);
    return root;
};

总结

需要注意的是如果用前后序递归遍历都是可以的,但是中序遍历是不可以的,会造成重复翻转等问题,如果非要用中序的话也不是不行,但会绕弯路。


 

101.对称二叉树

题目链接:101.对称二叉树

文档讲解:代码随想录/对称二叉树

视频讲解:视频讲解-对称二叉树

状态:已完成(1遍)

解题过程  

看到题目的第一想法

这题想了半天层序遍历,感觉只要在遍历每一层的时候,从队列里一次提出俩元素,然后将他们进行对比,每次对比完之后push进数组的元素也按照外侧和里侧的方式来配对,要左左和右右比较,左右和右左比较。

手搓一版如下:

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function(root) {
    let queue = [];
    queue.push(root.left);
    queue.push(root.right);
    while(queue.length){
        let len = queue.length;
        for(let i = 0;i<len;i++){
            let leftNode = queue.shift();
            let rightNode = queue.shift();
            if(leftNode == null&&rightNode == null)continue;//两个全是null
            if(leftNode==null||rightNode==null||leftNode.val!=rightNode.val)return false;//只有一个是null,以及都不是null但不相等
            queue.push(leftNode.left);//外侧
            queue.push(rightNode.right);//外侧
            queue.push(leftNode.right);//里侧
            //里侧
            queue.push(rightNode.left);
        }
    }
    return true;
};

提交直接成功,但是我预感有递归的简便方法了。 

 看完代码随想录之后的想法 

这道对称二叉树的不同点就在递归法只能够用后序遍历,只有后序遍历才能将所有子节点的信息收集,向上一层返回。

讲解代码如下:

var isSymmetric = function(root) {
    // 使用递归遍历左右子树 递归三部曲
    // 1. 确定递归的参数 root.left root.right和返回值true false 
    const compareNode = function(left, right) {
        // 2. 确定终止条件 空的情况
        if(left === null && right !== null || left !== null && right === null) {
            return false;
        } else if(left === null && right === null) {
            return true;
        } else if(left.val !== right.val) {
            return false;
        }
        // 3. 确定单层递归逻辑
        let outSide = compareNode(left.left, right.right);
        let inSide = compareNode(left.right, right.left);
        return outSide && inSide;
    }
    if(root === null) {
        return true;
    }
    return compareNode(root.left, root.right);
};

总结

递归三部曲:

  1. 确定递归的参数;
  2. 确定终止条件;
  3. 确定单层递归逻辑。
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值