Day14-二叉树-leetcode226,101,104,559,111

  1. 翻转二叉树
  • 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

  • 思路

  • 把每一个节点的左右孩子交换一下就可以了,就可以达到整体翻转的效果

  • 前序遍历、后序遍历

  • 递归:1. 函数参数及返回值 2. 确定终止条件 3. 处理逻辑

  • 前序:中左右,中,处理节点,交换左右孩子节点,

  • 层序:层序遍历也可以把每个节点的左右孩子都翻转一遍

// 用层序遍历(BFS)实现二叉树翻转
var invertTree = function(root) {
    // 用队列 queue 辅助层序遍历,把根节点先加入队列。
    let queue = []
    queue.push(root)
    // 如果根节点是 null,直接返回 null。
    if (root === null) {
        return null
    }
    // 只要队列不为空,就说明还有节点要处理。
    // len = queue.length,记录当前层节点数。
    // 用 for 循环遍历当前层的所有节点,每次弹出队首节点。
    while(queue.length !== 0) {
        let len = queue.length
        for (let i = 0; i< len; i++) {
            let node = queue.shift()
            // 交换当前节点的左右孩子,实现翻转。
            // 用临时变量保存左右孩子,然后互换。
            let tempLeft = node.left
            let tempRight = node.right
            node.left = tempRight
            node.right = tempLeft
            // 如果当前节点有左孩子,加入队列;有右孩子,也加入队列。
            // 这样下一轮 while 循环时会处理下一层的节点。
            node.left && queue.push(node.left)
            node.right && queue.push(node.right)
        }
    }
    // 最后返回翻转后的根节点。
    return root
};

// 递归版本的前序遍历
// 递归地交换每个节点的左右孩子即可实现二叉树翻转。
// 关键点:递归时要保存原右孩子,否则会被覆盖。
var invertTree = function(root) {
    // 递归终止条件:如果当前节点为空,直接返回 null。
    if (!root) {
        return null
    }
    // 暂存当前节点的右孩子,防止后面被覆盖。
    const rightNode = root.right
    // 递归翻转左子树,并把结果赋值给当前节点的右孩子。
    root.right = invertTree(root.left)
    // 递归翻转原来的右子树,并赋值给当前节点的左孩子
    root.left = invertTree(rightNode)
    // 返回翻转后的当前节点。
    return root
}

  1. 对称二叉树
  • 给你一个二叉树的根节点 root , 检查它是否轴对称。

  • 思路

  • 二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的

  • 后序遍历:需要收集孩子的信息,并向上一级返回;

  • 分为以下几种情况

      1. 左节点为空,右节点不为空,不对称,return false
      1. 左不为空,右为空,不对称 return false
      1. 左右都为空,对称,返回true
      1. 左右都不为空,比较节点数值,不相同就return false
      1. 左右节点都不为空,且数值相同的情况。
  • 单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。

    • 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
    • 比较内侧是否对称,传入左节点的右孩子,右节点的左孩子。
    • 如果左右都对称就返回true ,有一侧不对称就返回false 。
// 递归判断是否为对称二叉树
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. 二叉树的最大深度
  • 给定一个二叉树 root ,返回其最大深度。

  • 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

  • 思路

  • 高度:从下往上数,后序遍历,左右中,中间的处理过程返回给父节点,父节点再做一个加一,就知道自己的高度了

  • 深度:从上往下数,前序,中左右,中是处理过程,往下遍历一个就加一,

  • 根节点的高度就是二叉树的最大深度,所以用后序遍历也可以通过,

  • 递归:可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。1. 可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。2. 确定终止条件:如果为空节点的话,就返回0,表示高度为0。 3. 确定单层递归的逻辑:先求它的左子树的深度,再求右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。

  • 迭代:因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。在二叉树中,一层一层的来遍历二叉树,记录一下遍历的层数就是二叉树的深度。

// 递归 左右中
var maxdepth = function(root) {
    if (root === null) return 0
    // 左子树深度
    let leftDepth = maxdepth(root.left)
    // 右子树深度
    let rightDepth = maxdepth(root.right)
    // 二叉树的深度需要左右子树深度的最大值加上根节点这一层1
    let depth = 1 + Math.max(leftDepth, rightDepth)
    return depth
}
var maxdepth = function(root) {
    // 使用递归的方法,递归三部曲
    // 1. 确定递归函数的参数和返回值
    const getDepth = function(node) {
        // 2. 确定终止条件
        if (node === null) {
            return 0
        }
        // 3. 确定单层逻辑
        let leftDepth = getDepth(node.left)
        let rightDepth = getDepth(node.right)
        let depth = 1 + Math.max(leftDepth, rightDepth)
        return depth
    }
    return getDepth(root)
}
// 二叉树最大深度层级遍历
var maxDepth = function(root) {
    if(!root) return 0
    let count = 0
    const queue = [root]
    while(queue.length) {
        let size = queue.length
        // 层数+1
        count++
        while(size--) {
            let node = queue.shift()
            node.left && queue.push(node.left)
            node.right && queue.push(node.right)
        }
    }
    return count
}
  1. n叉树的最大深度
  • 给定一个 n 叉树,找到其最大深度。
  • 最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。
// 递归
var maxDepth = function(root) {
    if(!root) return 0
    let depth = 0
    for(let node of root.children) {
        depth = Math.max(depth, maxDepth(node))
    }
    return depth + 1
}
// 层序遍历
var maxDepth = function(root) {
    if (!root) return 0
    let count = 0;
    let queue = [root]
    while(queue.length) {
        let len = queue.length
        count++
        while(len--) {
            let node = queue.shift()
            for(let item of node.children) {
                item && queue.push(item)
            }
        }
    }
    return count
}

  1. 二叉树的最小深度
  • 给定一个二叉树,找出其最小深度。

  • 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

  • 说明: 叶子节点是指没有子节点的节点。

  • 思路

  • 注意:叶子节点,左右孩子都为空的节点才是叶子节点!

  • 递归法:1. 确定递归函数的参数和返回值,参数为要传入的二叉树根节点,返回的是深度;2. 确定终止条件,遇到空节点返回0,表示当前节点的高度为0;3. 确定单层递归的逻辑,左子树为空,右子树不空,则最小深度为1+右子树的最小深度,,右子树为空,左子树不为空,最小深度是1+左子树最小深度,,左右子树都不为空,返回左右子树最小深度的较小值+1

  • 迭代:层序,只有当左右孩子都为空的时候,才说明遍历到最低点了。如果其中一个孩子不为空则不是最低点

var minDepth = function(root) {
    if (!root) return 0
    // 到叶子节点 返回1
    if(!root.left && !root.right) return 1
    // 只有右节点时,递归右节点
    if(!root.left) return 1 + minDepth(root.right)
    // 只有左节点时,递归做节点
    if(!root.right) return 1 + minDepth(root.left)
    return Math.min(minDepth(root.left), minDepth(root.right)) + 1
}

// 迭代法,层序
var minDepth = function(root) {
    if(!root) return 0;
    const queue = [root];
    let dep = 0;
    while(true) {
        let size = queue.length;
        dep++;
        while(size--){
            const node = queue.shift();
            // 到第一个叶子节点 返回 当前深度 
            if(!node.left && !node.right) return dep;
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
    }
};



参考&感谢各路大神

posted @ 2025-06-10 18:40  安静的嘶吼  阅读(4)  评论(0)    收藏  举报