前端关于树的算法

184 阅读2分钟

自己搞下算法分类总结,以前大一还挺猛的,刷过三四百道,什么算法都会,现在不行了,只会些简单的,现在重新做人,把前端水平的算法题都写写,先把自己最不擅长的树总结下

  • 树的遍历 以前序遍历为例,因为和前端都有个前字,含递归和迭代,中序和后序也就位置变下,前序根左右,中序左根右,后序左右根
  //迭代
  function pre(treeNode) {
    if (!treeNode) {
      return
    }
    let stack = [treeNode];
    let res = [];
    while (stack.length) {
      let node = stack.pop()
      if (node.right) { stack.push(node.right) }
      if (node.left) { stack.push(node.left) }
      res.push(node.val)
    }
    return res;
  }
  //递归
  function pre(treeNode){
    let arr=[]
    if(!treeNode){
      return arr;
    }
    arr.push(treeNode.val)
    arr=arr.concat(pre(treeNode.left))
    arr=arr.concat(pre(treeNode.right))
    return arr;
  }
  • 重建二叉树 给个前序或后序加中序 把原本的树弄出来 因为前序是根左右,根就是第一个,中序是左根右,找到和根一样的就可以分出哪部分是左子树,哪边是右子树,然后递归
  function resetTree(pre, mid) {
    if (!pre.length) {
      return null
    }
    let root = pre[0]
    let index = mid.indexOf(root)
    let node = new treeNode(root)
    if (pre.length == 1) {
      return node
    }
    let leftMid = mid.slice(0, index)
    let rightMid = mid.slice(index + 1)
    let leftPre = pre.slice(1, leftMid.length)
    let rightPre = pre.slice(leftMid.length + 1, rightMid.length)
    node.left = resetTree(leftPre, leftMid)
    node.right = resetTree(rightPre, rightMid)
    return node;
  }
  • 层次遍历 就是每层都从左到右记录下 也可能会问从上到下,从左到右打印二叉树,还顺带解决了二叉树深度
  function levelOrder(tree) {
    let res = [];
    let queue = [tree];
    let level = 0;
    nodes[0] = tree;
    if (queue.length) {
      res[level] = []
      let len = queue.length
      while (len--) {
        let node = queue.shift();
        node.left && queue.push(node.left)
        node.right && queue.push(node.right)
        res[level].push(node.value)
      }
      level++;
    }
    return res;
  }
  • 二叉搜索树中第K小的元素 二叉搜索树是左<根<右,所以中序遍历的结果就是一个递增的数组,第k小就是第k个,当然也可以其他遍历,然后排序,然后直接找倒数第k个索引的值
var ksmall = function(root, k) {
    let res;
    function midOrder(root){
        if(!root) return root;
        midOrder(root.left);
        if(k === 0) return res;
        else{
            res = root.val;
            k--;
        }
        midOrder(root.right);
    }
    midOrder(root);
    return res;
};
  • 二叉树公共祖先 目前还没理解递归的方法,用map记录整个树的父子关系,然后记录p的整个父亲节点,用map检测q是否存在于p父亲节点中,没有就q=q的父亲节点
var lowestCommonAncestor = function(root, p, q) {
    let map=new Map()
    const search=(res)=>{
        if(res.left){
            map.set(res.left,res)
            search(res.left)
        }
        if(res.right){
            map.set(res.right,res)
            search(res.right)
        }
    }
    search(root)
    let parent=new Map()
    parent.set(p,p)
    while(map.has(p)){
        parent.set(map.get(p),map.get(p))
        p=map.get(p)
    }
    while(!parent.has(q)){
        q=map.get(q)
    }
    return q
};
  • 翻转二叉树 就遍历一遍每个节点的左右子树都对换一下
var invertTree = function(root) {
    if(root === null) return root;
    [root.left,root.right] = [root.right,root.left];
    invertTree(root.left);
    invertTree(root.right);
    return root;
};
  • 合并二叉树 就都有节点就相加没有就返回有的那个
var mergeTrees = function(t1, t2) {
    if(t1 && t2){
        t1.val += t2.val;
        t1.left = mergeTrees(t1.left,t2.left);
        t1.right = mergeTrees(t1.right,t2.right);
    }
    return t1 || t2;
};

害 简单的树的题目大概就这些吧 难的俺也尽力了 脑子不够用