美文网首页JavaScript 数据结构与算法
JavaScript 算法 (对称二叉树)

JavaScript 算法 (对称二叉树)

作者: 阿畅_ | 来源:发表于2020-05-16 18:14 被阅读0次
  • 题目
    给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

    1
   / \
  2   2
   \   \
   3    3

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/symmetric-tree

  • 二叉树的结构,如下图


    二叉树.png

首先构建二叉树结构

class Nodes {
  constructor(value) {
    this.value = value
    // 左右节点
    this.left = this.right = undefined
  }
}

  // 构建二叉树数据结构
class Tree {
  constructor(data) {
    // 临时存储所有节点
    let nodeList = []
    // 顶节点
    let root
    for (let i = 0; i < data.length; i++) {
      // 数据变成节点
      let node = new Nodes(data[i])          
      nodeList.push(node)
      if(i > 0) {
        // 计算当前节点属于哪一层,详细请看文章末尾
        let n = Math.floor(Math.sqrt(i+1))

        // 当前层的起始值 因为每层是 2 n 的平方
        let f = Math.pow(2, n) - 1
        // 记录上一层的起始点
        let p = Math.pow(2, n - 1) - 1

        // 找到当前节点的父节点
        let parent = nodeList[p + Math.floor((i - f) / 2)]
        // console.log(parent)
        // 把当前节点和 上一层的父节点关联起来
        // 判断是否有左节点,已有那就复制给又节点,因为二叉树只有左右两个节点
          if(parent.left) {
            parent.right = node
          } else {
            parent.left = node
          }
      }
    }
    // 取出第一个根节点
    root = nodeList.shift()
    nodeList.length = 0
    return root
  }
}

解释上面代码中几种计算 的意思

  1. Math.floor(Math.sqrt(i+1)) 计算当前是第几层
    • 每层计算是居于当前数 index + 1 然后平方根 后,向下取整得到
       例如数组为 
       [0, 1,2,3,4,5,6]
       循环遍历数组,当 index > 0 时开始计算,因为第一个是根
       第二层: 1 ,2  Math.floor(Math.sqrt(i+1))   计算有结果是 1
       第三层:3, 4, 5, 6  计算后结果是 2  
    
    
image.png
  1. Math.pow(2, n) - 1 ·当前层· 和 Math.pow(2, n - 1) - 1 ·上一层·

    • 如上图所示,每层数量是 2 * 当前层级, 而计算起始点要 - 1 因为数组是从 0 开始的
  2. nodeList[p + Math.floor((i - c) / 2)] 寻找父节点

    • p 表示上一层的起始点,c 当前层的起始点, i 数组的 index
    • 找出 5 和 6 的父节点
      • 5 的 i 是 5, c 是 3, p 是 1, ---》 结果是 2
    • 3 和 4 的父节点
      • 3 -> i 是 3, c 是 3 , p 是 1 ----》 结果是 1

验证二叉树是否对称

  • 如图,把每个节点分成如下方式,分别验证左右是否相同
  // 验证对称 二叉树
  // 递归把 二叉树的 左右节点比较
  static isSymmetry(root) {
    if (!root) {
      return false
    }
    let verify = (left, right) => {
      if (!left && !right) {
        return true
      }
      // 左或右 没有,或者 左右 的值不相等
      if ((left && !right) || (!left && right) || (left.value !== right.value)) {
        return false
      }
      return verify(left.left, right.right) && verify(left.right, right.left)
    }

    return verify(root.left, root.right)
  }
image.png

最后所有代码

class Nodes {
  constructor(value) {
    this.value = value
    // 左右节点
    this.left = this.right = undefined
  }
}

// 构建二叉树数据结构
class Tree {
  constructor(data) {
    // 临时存储所有节点
    let nodeList = []
    // 顶节点
    let root
    for (let i = 0; i < data.length; i++) {
      // 数据变成节点
      let node = new Nodes(data[i])          
      nodeList.push(node)
      if(i > 0) {
        // 计算当前节点属于哪一层,
        let n = Math.floor(Math.sqrt(i+1))

        // 当前层的起始点 因为每层是 2 n 的平方
        let c = Math.pow(2, n) - 1
        // 记录上一层的起始点
        let p = Math.pow(2, n - 1) - 1

        // 找到当前节点的父节点
        console.log(p + Math.floor((i - c) / 2))
        let parent = nodeList[p + Math.floor((i - c) / 2)]
        // console.log(parent)
        // 把当前节点和 上一层的父节点关联起来
        // 判断是否有左节点,已有那就复制给又节点,因为二叉树只有左右两个节点
        if(parent.left) {
          parent.right = node
        } else {
          parent.left = node
        }
      }
    }
    // 取出第一个根节点
    root = nodeList.shift()
    nodeList.length = 0
    return root
  }

  // 验证对称 二叉树
  // 递归把 二叉树的 左右节点比较
  static isSymmetry(root) {
    if (!root) {
      return false
    }
    let verify = (left, right) => {
      if (!left && !right) {
        return true
      }
      // 左或右 没有,或者 左右 的值不相等
      if ((left && !right) || (!left && right) || (left.value !== right.value)) {
        return false
      }
      return verify(left.left, right.right) && verify(left.right, right.left)
    }

    return verify(root.left, root.right)
  }
}

const res = new Tree([1,2,2,3,4,4,3])
console.log(res)
console.log('校验二叉树', Tree.isSymmetry(res)) // true

相关文章

  • 每日Leetcode—算法(10)

    100.相同的树 算法: 101.对称二叉树 算法: 104.二叉树的最大深度 算法: 107.二叉树的层次遍历 ...

  • JavaScript 算法 (对称二叉树)

    题目给定一个二叉树,检查它是否是镜像对称的。 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 但是下面这...

  • 二叉树--自对称判断

    今天学习的算法是判断二叉树是否自对称。 题目介绍 对称二叉树的特点是将跟节点的左右子树翻转后,树与原来保持完全一致...

  • 关于函数递归和迭代的转化, 及尾递归相关知识的接触和思考

    javascript实现数据结构: 树和二叉树,二叉树的遍历和基本操作 js 二叉树 【数据结构与算法】深入浅出递...

  • 加密算法的应用

    加密算法的应用 [TOC] 加密算法 加密算法主要分为对称加密和非对称加密。 对称加密 对称加密采用了对称密码编码...

  • 【LeetCode】101-对称二叉树

    对称二叉树 题目 给定一个二叉树,检查它是否是镜像对称的。 例如,二叉树 [1,2,2,3,4,4,3] 是对称的...

  • Java 加密算法

    一、消息摘要算法 二、Base64 对称加密算法 三、Des 对称加密算法 四、Aes 对称加密算法 五、Pbe ...

  • LeetCode-101-对称二叉树

    LeetCode-101-对称二叉树 101. 对称二叉树[https://leetcode-cn.com/pro...

  • DES加密算法原理

    什么是对称密码算法 网络安全通信中要用到两类密码算法,一类是对称密码算法,另一类是非对称密码算法。对称密码算法有时...

  • 常用加密算法

    1 常用加密算法 常用加密算法有 对称加密算法、非对称加密算法、Hash算法 对称加密算法 加密和解密使用相同的秘...

网友评论

    本文标题:JavaScript 算法 (对称二叉树)

    本文链接:https://www.haomeiwen.com/subject/gwoanhtx.html