关于二叉树的算法(JavaScript)

二叉树的遍历

前序遍历

中左右

function preorderTraversal( root ) {
    let res = []
    preOrder(root)
    return res
    function preOrder(node){
        if(node === null) return
        res.push(node.val)
        preOrder(node.left)
        preOrder(node.right)
    }
}

中序遍历

左中右

function inorderTraversal( root ) {
    let res = []
    inorderTravese(root)
    return res
    function inorderTravese(node){
        if(node === null) return null
        inorderTravese(node.left)
        res.push(node.val)
        inorderTravese(node.right)
    }
}

后序遍历

左右中

function postorderTraversal( root ) {
    let res = []
    postorderTraverse(root)
    return res
    function postorderTraverse(node){
        if(node === null) return
        postorderTraverse(node.left)
        postorderTraverse(node.right)
        res.push(node.val)
    }
}

层序遍历

function levelOrder( root ) {
    const res = [], queue = []
    if(root === null) return null
    queue.push(root)
    while(queue.length){
        let length = queue.length
        const curLevel = []
        while(length --){
            let node = queue.shift()
            curLevel.push(node.val)
            node.left && queue.push(node.left)
            node.right && queue.push(node.right)
        }
        res.push(curLevel)
    }
    return res
}

二叉树的最大深度

二叉树的最大深度
输入:{1,2}
返回值:2
方法:利用层序,有几层深度就是多少

function maxDepth( root ) {
    let res = 0
    if(root === null) return res
    const queue = []
    queue.push(root)
    while(queue.length){
        let len = queue.length
        while(len --){
            let node = queue.shift()
            node.left && queue.push(node.left)
            node.right && queue.push(node.right)
        }
        res ++
    }
    return res
}
// 递归方法
function maxDepth( root ) {
    // write code here
    if(root === null) return 0
    let max = 0
    if(root.left){
        max = Math.max(max, maxDepth(root.left))
    }
    if(root.right){
        max = Math.max(max, maxDepth(root.right))
    }
     
    return max + 1
}

二叉树中和为某一值的路径

二叉树中和为某一值的路径
输入:{5,4,8,1,11,#,9,#,#,2,7},22
返回值:true
方法:递归

function hasPathSum(root, sum) {
    // write code here
    // 空树
    if (root === null) return false
    function dfs(node, sum) {
        if (node === null) return false
        // 已经遍历到叶子节点
        if (node.left === null && node.right === null && node.val === sum) {
            return true
        }
        return dfs(node.left, sum - node.val) || dfs(node.right, sum - node.val)
    }
    return dfs(root, sum)
}

二叉搜索树与双向链表

二叉搜索树与双向链表
方法:利用中序遍历

function Convert(pRootOfTree) {
    // head:头节点
    // pre:记录上一节点
    let head = null, pre = null
    // 中序遍历
    function traversal(node) {
        if (node === null) {
            return
        }
        traversal(node.left)
        // 处理当前节点
        // 如果是前序遍历的第一个节点,head始终指向该节点
        if (node.left === null && head === null) {
            head = node
            pre = node
        } else {
            // 前一节点的右指针指向当前节点
            // 当前节点的左指针指向前一节点
            // 更新pre
            pre.right = node
            node.left = pre
            pre = node
        }
        traversal(node.right)
    }
    traversal(pRootOfTree)
    return head
}

对称二叉树

对称二叉树

function isSymmetrical(pRoot) {
    function isSym(left, right) {
        // 没有子节点
        if (left === null && right === null) {
            return true
        }
        // 只有一个节点为空
        if (left === null || right === null) {
            return false
        }
        // 数值不相等
        if (left.val !== right.val) {
            return false
        }
        return isSym(left.left, right.right) && isSym(left.right, right.left)
    }
    if (pRoot === null) {
        return true
    }
    return isSym(pRoot.left, pRoot.right)
}

合并二叉树

合并二叉树
都存在的结点,就将结点值加起来,否则空的位置就由另一个树的结点来代替。

function mergeTrees( t1 ,  t2 ) {
    if(t1 === null) return t2
    if(t2 === null) return t1
    t1.val = t1.val + t2.val
    t1.left = mergeTrees(t1.left, t2.left)
    t1.right = mergeTrees(t1.right, t2.right)
    return t1
}

二叉树的镜像

二叉树的镜像

function Mirror( pRoot ) {
    if(pRoot === null){
        return null
    }
    let tmp = pRoot.left
    pRoot.left = pRoot.right
    pRoot.right = tmp
    Mirror(pRoot.left)
    Mirror(pRoot.right)
    return pRoot
}

判断

判断是不是二叉搜索树

判断是不是二叉搜索树
方法:中序遍历,然后判断是否是递增

function isValidBST(root) {
    // 中序遍历,判断是否递增
    function travel(node) {
        if (node) {
            travel(node.left)
            arr.push(node.val)
            travel(node.right)
        }
    }
    let arr = []
    travel(root)
    for (let i = 1; i < arr.length; i++) {
        if (arr[i] <= arr[i - 1]) {
            return false
        }
    }
    return true
}

判断是不是完全二叉树

判断是不是完全二叉树
方法:利用层序遍历,如果是完全二叉树,直到最后才会遇到null

function isCompleteTree( root ) {
    let queue = []
    queue.push(root)
    // 标记是否遇到空节点
    let flag =false
    while(queue.length){
        const node = queue.shift()
        // 遇到空节点则标记成true
        if(node === null) {
            flag = true
        } else {
            // 当前节点不是空节点,但flag是true,则说明不是完全二叉树
            if(flag === true) {
                return false
            }
            queue.push(node.left)
            queue.push(node.right)
        }
    }
    return true
}

判断是不是平衡二叉树

判断是不是平衡二叉树
方法:求出左右子树的最大深度,绝对值小于等于1。特别注意:左右子树也要满足平衡二叉树

function IsBalanced_Solution(pRoot) {
    if (pRoot === null) return true
    // 求最大深度
    function maxDeep(node) {
        let max = 0
        if (node.left) {
            max = Math.max(max, maxDeep(node.left))
        }
        if (node.right) {
            max = Math.max(max, maxDeep(node.right))
        }
        return max + 1
    }
    // 求左右子树的最大深度
    let leftDeep = 0, rightDeep = 0
    if (pRoot.left) {
        leftDeep = maxDeep(pRoot.left)
    }
    if (pRoot.right) {
        rightDeep = maxDeep(pRoot.right)
    }
    // 左右子树的最大深度差小于等于1 且 左右子树都满足平衡二叉树
    return Math.abs(leftDeep - rightDeep) <= 1
        && IsBalanced_Solution(pRoot.left)
        && IsBalanced_Solution(pRoot.right)
}

最近公共祖先

二叉树的最近公共祖先

二叉树的最近公共祖先

方法:如果left和right的返回值都不为空,则返回root;否则返回不为空的那个。

function TreeNode(val) {
   this.val = val;
   this.left = this.right = null;
}

var lowestCommonAncestor1 = function(root, p, q){
    function travelTree(node, p, q){
        if(node === null || node === p || node === q){
            return node
        }
        let left = travelTree(node.left, p, q)
        let right = travelTree(node.right, p, q)
        if(left !== null && right !== null){
            return node
        }
        if(left === null){
            return right
        }
        return left
    }
    return travelTree(root, p, q)
}

二叉搜索树的最近公共祖先

二叉搜索树的最近公共祖先
方法:如果val大于p和q的val,则从节点的左子树开始找

var ancestor = function(root, p, q){
    while (root) {
        if(root.val > p.val && root.val > q.val){
            root = root.left
        }else if(root.val < q.val && root.val < p.val){
            root = root.right
        }else{
            return root
        }
    }
    return null
}

构建二叉树

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

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

var buildTreefromPreInorder = function(preorder, inorder){
    if(!preorder.length) return null
    let root = new TreeNode(preorder[0])
    let mid = inorder.findIndex(number => number === root.val)
    root.left = buildTreefromPreInorder(preorder.slice(1, mid + 1), inorder.slice(0, mid))
    root.right = buildTreefromPreInorder(preorder.slice(mid + 1, preorder.length), inorder.slice(mid + 1, inorder.length))
}

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

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

// 中序+后序
var buildTreefromPostInorder = function(inorder, postorder){
    if(!postorder.length) return null
    // 构建根节点
    let root = new TreeNode(postorder[postorder.length - 1])
    // 寻找分割点
    let index = inorder.findIndex(number => number === root.val)
    root.left = buildTreefromPostInorder(inorder.slice(0,index), postorder.slice(0,index))
    root.right = buildTreefromPostInorder(inorder.slice(index + 1, inorder.length), postorder.slice(index, postorder.length - 1))
    return root
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值