leetcode基础-二叉树

概念

二叉树

二叉树是一种 每个节点最多有两个子树 的树状结构

  • 深度优先遍历有三种顺序:

    前序:中→左→右

    中序:左→中→右

    后序:左→右→中(删除二叉树时会使用的遍历)

  • 广度优先遍历

    层序遍历(也可以使用深度遍历的思想)

遍历

树形结构

/**
 * 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 preorderTraversal = function(root) {
    let result = []
    var preOrderTraverseNode = (node) => {
        if(node) {
            // 先根节点
            result.push(node.val);
            // 然后遍历左子树
            preOrderTraverseNode(node.left);
            // 再遍历右子树
            preOrderTraverseNode(node.right);
        }
    }
    preOrderTraverseNode(root);
    return result;
};

// 利用栈辅助 遍历
const preOrderTraverseUnRecur = (root) => {
    let res = [];
    let stack = [root];
		let node = null;

    while(stack.length !== 0) {
        node = stack.pop();
        // 第一步的时候,先访问的是根节点
        res.push(node.val);

        if(node.right) {
            stack.push(node.right)
        }

        // 因为pop是取出最后一个元素,所以我们要确保首先拿到的是左节点
        if(node.left) {
            stack.push(node.left)
        }
    }
		return res;
}

中序:左→中→右

// 递归
var inorderTraversal = function(root) {
    let result = []
    var preOrderTraverseNode = (node) => {
        if(node) {
            // 先遍历左子树
            preOrderTraverseNode(node.left);
						// 然后根节点
            result.push(node.val);
            // 再遍历右子树
            preOrderTraverseNode(node.right);
        }
    }
    preOrderTraverseNode(root);
    return result;
};
// 非递归
function inorderTraversal (root) {
    let res = [];
    let stack = [];
    while(stack.length > 0 || root){
        if(root){
            stack.push(root);
            root = root.left;
        } else {
            root = stack.pop();
            if(root.val) res.push(root.val);
            root = root.right;
        }
    }
    return res;
}

后序:左→右→中

// 递归
var inorderTraversal = function(root) {
    let result = []
    var preOrderTraverseNode = (node) => {
        if(node) {
            preOrderTraverseNode(node.left);
            preOrderTraverseNode(node.right);
						result.push(node.val);
        }
    }
    preOrderTraverseNode(root);
    return result;
};

// 非递归版本
var postorderTraversal = function(root) {
    let res = [];
    let stack = [];
    if(root) stack.push(root);
    while(stack.length){
        root = stack.pop();
        if(root.val) res.**unshift**(root.val);
        if(root.left) stack.push(root.left);
				if(root.right) stack.push(root.right);
    }
    return res;
};

// 解题思路: 后序遍历与前序遍历不同的是:
// 后序遍历是左右根
// 而前序遍历是根左右
// 如果我们把前序遍历的 list.push(node.val) 变更为 list.unshift(node.val) (遍历结果逆序),那么遍历顺序就由 根左右 变更为 右左根
// 然后我们仅需将 右左根 变更为 左右根 即可完成后序遍

层序遍历

// 层序遍历 
// // DFS(深度优先遍历)
var levelOrder = function(root) {
    let res = [];
    let levelTree = function(node, level){
        if(!res[level]) res[level] = [];
        if(node.val !== undefined) res[level].push(node.val);
        if(node.left) levelTree(node.left, level+1);
        if(node.right) levelTree(node.right, level+1);
    }
    if(root) levelTree(root, 0);
    return res;
};

// BFS(广度优先遍历)
var levelOrder = function(root) {
    let res = [];
    let queue = [];
    if(root) queue.unshift(root);
    while(queue.length){
        let cur = [];
        let nextQue = [];
        while(queue.length){
            let node = queue.shift();
            if(node.val !== undefined) cur.push(node.val);
            if(node.left) nextQue.push(node.left);
            if(node.right) nextQue.push(node.right);
        }
        res.push(cur);
        queue = nextQue;
    }
    return res;
};

常用考察

二叉树最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

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

// 深度遍历,比较每条路径
var maxDepth = function(root) {
    if(!root) return 0;
    let maxDep = 0;
    const deep = function(root, n){
        if(root.val) n++;
        maxDep = Math.max(maxDep, n);
        if(root.left) deep(root.left, n);
        if(root.right) deep(root.right, n);
    }
    deep(root, 0);
    return maxDep;
};

// 广度遍历,记录每层的树节点
var maxDepth = function(root) {
    if(!root) return 0;
    let maxDep = 0;
    let queue = [root];
    while(queue.length){
        maxDep++;
        let curQue = [];
        while(queue.length){
            let node = queue.shift();
            if(node.left) curQue.push(node.left);
            if(node.right) curQue.push(node.right);
        }
        queue = curQue;
    }
    return maxDep;
};

对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

// 递归
var isSymmetric = function(root) {
    if (root === null) return true;
    const isMirror = function(left, right){
        if(left === null && right === null) return true;
        if(left === null || right === null) return false;
        return (left.val === right.val) && isMirror(left.left, right.right) && isMirror(left.right, right.left);
    }
    return isMirror(root.left, root.right);
};
// 迭代
var isSymmetric = function(root) {
    if (root == null) return true
    let queue = [root]
    while(queue.length){
        let curArr = [];
        let nextQue = [];
        while(queue.length){
            let node = queue.shift();
            if(node === null){
                curArr.push('null');
            } else {
                curArr.push(node.val);
                nextQue.push(node.left);
                nextQue.push(node.right);
            }
        }
        if(Array.from(curArr).reverse().toString() !== curArr.toString()) return false;
        queue = nextQue;
    }
    return true;
};

路径总和

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

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

var hasPathSum = function(root, targetSum) {
    if(root === null) return false;
    if(root.val === targetSum && root.left == null && root.right == null) return true;
    targetSum = targetSum - root.val;
    return hasPathSum(root.left, targetSum) || hasPathSum(root.right, targetSum);
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值