算法篇——二叉树大集合上篇(js版)

222.完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
链接:https://leetcode.cn/problems/count-complete-tree-nodes

var countNodes = function(root) {
    var res = [], queue = [];
    var sumLen = 0;
    if(!root) return 0;
    queue.push(root);
    while(queue.length) {
        let len = queue.length;
        let curNode = [];
        for(let i = 0;i < len; i++) {
            let node = queue.shift();
            curNode.push(node.val);
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
        res.push(curNode);
        sumLen += curNode.length;
    }
    return sumLen;
};

110.平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

var isBalanced = function(root) {
    return booleanisBalanced(root) != -1;
};
var booleanisBalanced = function(root) {
    if (!root) return 0;
    // 当某一子树不平衡就返回
    let left = booleanisBalanced(root.left);
    if (left == -1) return -1;
    let right = booleanisBalanced(root.right);
    if (right == -1) return -1;
    // 如果左右子树层高相差小于2  平衡:返回实际层高  否则返回-1
    return Math.abs(left - right) < 2 ? Math.max(left, right) + 1 : -1;
};

257. 二叉树的所有路径

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

链接:力扣

var binaryTreePaths = function(root) {
    // 如果是空树
    if(!root) return [];
    var res = [], cur = '';
    pathNode(root, res, cur);
    return res;
};
var pathNode = (root, res, cur) => {
    if(!root) return;
    // 如果没有左右孩子,说明是叶子节点
    if(!root.left && !root.right) {
        // 在当前字符串上加上叶子结点
        cur += root.val;
        res.push(cur);
        return;
    }
    // 非叶子节点加 →
    else cur += root.val + '->';
    //递归左子树
    pathNode(root.left, res, cur);
    //递归右子树
    pathNode(root.right, res, cur);
}

404.左叶子之和

给定二叉树的根节点 root ,返回所有左叶子之和。

链接:力扣

// 迭代
var sumOfLeftLeaves = function(root) {
    if(!root) return null;
    var list = [root], sum = 0;
    while(list.length) {
        var cur = list.shift();
        // 左节点是叶子节点时
        if(cur.left && !cur.left.left && !cur.left.right) 
            sum += cur.left.val;
        // 遍历左右子树
        cur.left && list.push(cur.left);
        cur.right && list.push(cur.right);
    }
    return sum;
};

 或

// 递归
var sumOfLeftLeaves = function(root) {
    return sumNode(root);
};
var sumNode = (root) => {
    if(!root) return null;
    // 遍历左右子树
    var lval = sumNode(root.left);
    var rval = sumNode(root.right);
    // 单层递归
    var mid = 0;
    // 当前是左叶子节点
    if(root.left && !root.left.left && !root.left.right) mid += root.left.val;
    // 左子树的左叶子节点+右子树的左叶子节点
    var sum = mid + lval + rval;
    return sum;
}

513.找树左下角的值

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

链接:力扣

var findBottomLeftValue = function(root) {
    var list = [root], res = 0;
    while(list.length) {
        var len = list.length;
        for(var i = 0; i < len; i++) {
            var cur = list.shift();
            if(i == 0) res = cur.val;
            cur.left && list.push(cur.left);
            cur.right && list.push(cur.right);
        }
    }
    return res;
};

112. 路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。
链接:https://leetcode.cn/problems/path-sum

  

var hasPathSum = function(root, targetSum) {
    var sum = 0;
    return pathSum(root, sum, targetSum);
};
var pathSum = (root, sum, targetSum) => {
    if(!root) return false;
    // 如果没有左右孩子,说明是叶子节点
    if(!root.left && !root.right) {
        // 在当前和上加上叶子结点的值为当前路径的sum
        sum += root.val;
        return sum == targetSum ? true : false;
    }
    // 非叶子节点只进行相加
    else sum += root.val;
    // 遍历左右子树
    return pathSum(root.left, sum, targetSum) || pathSum(root.right, sum, targetSum);  
}

106.从中序与后序遍历序列构造二叉树 

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
链接:https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal

var buildTree = function(inorder, postorder) { 
    if(!inorder.length) return null;
    // 根节点是后序遍历的最后一个元素
    var rootVal = postorder[postorder.length-1];
    // 切割遍历数组的下标
    var index = inorder.indexOf(rootVal);
    // 中序左数组
    var midLeft = inorder.slice(0, index);
    // 中序右数组
    var midRight = inorder.slice(index+1, inorder.length);
    // 后序左数组
    var lastLeft = postorder.slice(0, index);
    // 后序右数组
    var lastRight = postorder.slice(index, postorder.length-1);
    // 创建二叉树
    var root = new TreeNode(rootVal);
    // 创建左子树
    root.left = buildTree(midLeft, lastLeft);
    // 创建右子树
    root.right = buildTree(midRight, lastRight);
    return root;
};

105.从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal

  

var buildTree = function(preorder, inorder) {
    if(!inorder.length) return null;
    // 根节点是前序遍历的第一个元素
    var rootVal = preorder[0];
    // 切割遍历数组的下标
    var index = inorder.indexOf(rootVal);
    // 中序左数组
    var midLeft = inorder.slice(0, index);
    // 中序右数组
    var midRight = inorder.slice(index+1, inorder.length);
    // 前序左数组
    var preLeft = preorder.slice(1, midLeft.length+1);
    // 前序右数组
    var preRight = preorder.slice(midLeft.length+1, preorder.length);
    // 创建二叉树
    var root = new TreeNode(rootVal);
    // 创建左子树
    root.left = buildTree(preLeft, midLeft);
    // 创建右子树
    root.right = buildTree(preRight, midRight);
    return root;
};

654.最大二叉树

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums 构建的 最大二叉树 。
链接:https://leetcode.cn/problems/maximum-binary-tree

var constructMaximumBinaryTree = function(nums) {
    var root = maxVal(nums, 0, nums.length-1);
    return root;
};
var maxVal = (list, left, right) => {
    if(left > right) return null;
    let tarVal = -1, tarIndex = -1;
    for(var i = left; i <= right; ++i) {
        if(list[i] > tarVal) {
            tarVal = list[i];
            tarIndex = i;
        }
    }
    var root = new TreeNode(tarVal);
    root.left = maxVal(list, left, tarIndex-1);
    root.right = maxVal(list, tarIndex + 1, right);
    return root;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为何幸福如驴薄饼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值