树详解(上)|LeetCode|javascript|递归法|一招鲜吃遍天

准备知识

相关术语

树中每个元素都叫做节点,位于树顶部的节点叫做根节点,没有父节点,节点分祖先节点、后代节点

深度:节点祖先节点的个数

树的高度:最大的节点的深度

二叉搜索树:二叉树的一种,但是左侧子节点值比父节点的值小,右侧子节点的值比父节点的值大
LeetCode上最常用二叉搜索树


注:下列题目使用递归,迭代法待续(2020.05.09)

N叉树的后序遍历

/**
 * // Definition for a Node.
 * function Node(val,children) {
 *    this.val = val;
 *    this.children = children;
 * };
 */

/**
 * @param {Node} root
 * @return {number[]}
 */
var postorder = function (root) {
    let res = [];
    const fun = (root) => {
        if (root === null) {
            return null;
        }

        for (let i = 0; i < root.children.length; i++) {
            fun(root.children[i])
        }
            res.push(root.val)

    }
    fun(root);
    return res;
};

N叉树的前序遍历

/**
 * // Definition for a Node.
 * function Node(val, children) {
 *    this.val = val;
 *    this.children = children;
 * };
 */

/**
 * @param {Node} root
 * @return {number[]}
 */
var preorder = function(root) {
   let res = [];
   const fun = (root) =>{
       if(root === null){
           return null;
       }
        res.push(root.val)
       for(let i = 0;i<root.children.length;i++){
           fun(root.children[i])
       }
       
   }
   fun(root);
   return res;
};

前后的不同

在于内部函数里面res.push(root.val)在递归调用的前面还是后面

二叉树

二叉树的前序遍历(根左右)

var preorderTraversal = function(root) {
  const res = []
  function traversal (root) {
    if (root !== null) {
      res.push(root.val) // 访问根节点的值
      traversal(root.left) // 递归遍历左子树
      traversal(root.right) // 递归遍历右子树
    }
  }
  traversal(root)
  return res
}

二叉树的中序遍历(左根右)

var inorderTraversal = function(root) {
  const res = []
  function traversal (root) {
    if (root !== null) {
      traversal(root.left)
      res.push(root.val)
      traversal(root.right)
    }
  }
  traversal(root)
  return res
}

二叉树的后序遍历(左右根)

var postorderTraversal = function(root) {
  const res = []
  function traversal (root) {
    if (root !== null) {
      traversal(root.left)
      traversal(root.right)
      res.push(root.val)
    }
  }
  traversal(root)
  return res
}

分析

同理,在于res.push(root.val)在内部函数中的位置,因为本语句访问根节点的值,代表根的位置

相同的树

判断两树是否相同

var isSameTree = function(p, q) {
  function traversal (root1, root2) {
    if (root1 === null && root2 !== null) {
      return false
    } else if (root1 !== null && root2 === null) {
      return false
    } else if (root1 === null && root2 === null) {
      return true
    } else {
      return  root1.val === root2.val && traversal(root1.left, root2.left) && traversal(root1.right, root2.right)
    }
  }
  return traversal(p, q)
}

分析

1.有一个空,一个非空,必不相同
2.排除以上情况后,只存在全空,或者全不为空,全空必相同
3.排除以上情况后,只存在全不为空,根节点值不等,必不想等
4.排除以上情况后,返回递归两树的根节点的左子节点 与上 两树根节点的右子节点

翻转二叉树

/**
 * 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){
        return null;
    }
    // 交换
    var temp = root.left;
    root.left = root.right;
    root.right = temp;
    // 递归左右节点
    invertTree(root.left)
    invertTree(root.right)

    return root
};

分析

1.如果空,没必要翻转,返回null
2.根节点的左右节点交换(临时变量)
2.递归

二叉树的最大深度

var maxDepth = function(root) {
    // 递归向下
    // 深度是左右节点最大深度加1 
    return root? Math.max(maxDepth(root.left),maxDepth(root.right))+1 : 0;
};

分析

一棵树的最大深度是左右子树中深度最大的一方+1(一个根节点)
如果为空,结束递归

N叉树的最大深度

var maxDepth = function (root) {
    if (!root) return 0;
    let max = 0;
    for (let i  of root.children) {
        max = Math.max(max, maxDepth(i));
    }
    return max + 1;
};


分析

和二叉树的区别在于要遍历一下根节点的每个子节点,然后取最大的
在一组数中取最大的方法是先将第一个存入max,之后每个和max比较,谁大谁设置为max
最后+1

以上方法一言以蔽之:递归

该方法较为简单,可尝试迭代


迭代法

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值