Skip to content

N叉树遍历

ts
class TreeNode {
  constructor(val, children: TreeNode[]) {
    this.value = value
    this.children = children
  }
}

// 循环
const traverse = (root: TreeNode) => {
  for(let child of root.children) {
    traverse(child)
  }
}

树的对比

相同的树

js
var isSameTree = function(p, q) {
  if(p == null && q == null) {
    return true;
  } else if(p === null || q == null) {
    return false;
  } else if(p.val !== q.val) {
    return false;
  }
  return isSameTree(p.left, q.left) && isSameTree(p.right, q.right)
};

对称二叉树

js
var isSymmetric = function(root) {
  if(!root) return true

  const check = (left, right) => {
    if(!left && !right) return true
    if(!left || !right) return false
    if(left.val !== right.val) return false
    return check(left.left, right.right) && check(left.right, right.left)
  }

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

翻转二叉树

js
var invertTree = function(root) {
  if(!root) {
    return root;
  }
  const newRoot = new TreeNode(root.val)
  newRoot.left = invertTree(root.right);
  newRoot.right = invertTree(root.left);
  return newRoot
};

路径计算相关

树的最大深度

js
var maxDepth = function(root) {
  if(!root) {
    return 0
  }
  const left = maxDepth(root.left)
  const right = maxDepth(root.right)
  return Math.max(left, right) + 1
}

树的最小深度

层序遍历,无左右子节点则返回当前的深度

js
var minDepth = function(root) {
  if(!root) return 0
  const queue = []
  queue.push(root)
  let depth = 0
  while(queue.length) {
    depth++
    const currentLevelSize = queue.length
    for(let i = 0; i < currentLevelSize; i++) {
      const node = queue.shift()
      if(!node.left && !node.right) return depth
      if (node.left) queue.push(node.left)
      if (node.right) queue.push(node.right) 
    }
  }
  return depth
}

求根节点到叶节点数字之和

js
var sumNumbers = function(root) {
  const dfs = (root, preSum) => {
    if(root === null) {
      return 0;
    }
    const sum = preSum * 10 + root.val;
    if (!root.left && !root.right) {
      return sum;
    }
    return dfs(root.left, sum) + dfs(root.right, sum);
  }

  return dfs(root, 0);
}

路径总和

DSF实现

js
var hasPathSum = function(root, targetSum) {
  if (!root) {
    return false;
  }

  if (!root.left && !root.right) {
    return root.val === targetSum;
  }

  return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}

BSF实现

js
var hasPathSum = function(root, targetSum) {
  if(!root) {
    return false
  }
  var queue1 = [root]
  var queue2 = [root.val]
  while(queue1.length){
    var node = queue1.shift();
    var rootVal = queue2.shift();
    if(node.left == null && node.right == null && rootVal == targetSum){
      return true;
    }
    if(node.left){
      queue1.push(node.left);
      queue2.push(node.left.val + rootVal);
    }
    if(node.right){
      queue1.push(node.right);
      queue2.push(node.right.val + rootVal);
    }
  }
  return false;
}

重建二叉树

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

js
var buildTree = function(inorder, postorder) {
  const fn = (inStart, inEnd, postStart, postEnd) => {
    if(inStart > inEnd || postStart > postEnd) {
      return null
    }
    const rootval = postorder[postEnd]
    const midIndex = inorder.indexOf(rootval)
    const leftNodeNum = midIndex - inStart
    const root = new TreeNode(rootval)
    root.left = fn(inStart, midIndex - 1, postStart, postStart + leftNodeNum - 1)
    root.right = fn(midIndex + 1, inEnd, postStart + leftNodeNum, postEnd - 1)
    return root
  }
  return fn(0, inorder.length - 1, 0, postorder.length - 1)
};

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

js
var buildTree = function(preorder, inorder) {
  const recursive = (preStart, preEnd, inStart, inEnd) => {
    if(preStart > preEnd || inStart > inEnd) {
      return null
    }
    const rootVal = preorder[preStart]
    const mid = inorder.indexOf(rootVal)
    const root = new TreeNode(rootVal)
    const leftNum = mid - inStart
    root.left = recursive(preStart + 1, preStart + leftNum, inStart, mid - 1)
    root.right = recursive(preStart + leftNum + 1, preEnd,  mid + 1, inEnd)
    return root
  }
  return recursive(0, preorder.length - 1, 0, inorder.length -1)
};

二叉树层序遍历

二叉树的层平均值

js
var averageOfLevels = function(root) {
    const stack = [];
  const res = [];
  if(root){
    stack.push(root)
  }
  while(stack.length) {
    const len = stack.length;
    let sum = 0;
    for(let i = 0; i < len; i++) {
      const node = stack.shift();
      sum += node.val;
      if(node.left) {
        stack.push(node.left)
      }
      if(node.right) {
        stack.push(node.right)
      }
    }
    res.push(sum / len);
  }
  return res
};

二叉树的右视图

js
var rightSideView = function(root) {
  const stack = [];
  const res = [];
  if (root) {
    stack.push(root)
  }
  while(stack.length) {
    const len = stack.length;
    for (let i = 0; i < len; i++) {
      const node = stack.shift()
      if (i === len - 1){
        res.push(node.val)
      }
      if (node.left) {
        stack.push(node.left)
      }
      if(node.right) {
        stack.push(node.right)
      }
    } 
  }
  return res;
};

二叉树的锯齿形层序遍历

js
var zigzagLevelOrder = function(root) {
  const stack = [];
  const res = [];
  if (root) {
    stack.push(root)
  }
  let level = 1
  while (stack.length) {
    res.push([]);
    const len = stack.length;
    for (let i = 0; i < len; i++) {
      const node = stack.shift()
      if (level % 2 === 1) {
        res[res.length - 1].push(node.val)
      } else [
        res[res.length - 1].unshift(node.val)
      ]
      if (node.left) {
        stack.push(node.left)
      }
      if (node.right) {
        stack.push(node.right)
      }
    }
    level++
  }
  return res;
};

二叉搜索树

递增顺序搜索树

js
var increasingBST = function(root) {
  const dummyNode = new TreeNode(-1);
  let resNode = dummyNode;
  const dsf = function(root) {
    if (!root) {
      return
    }
    dsf(root.left)
    resNode.right = root;
    root.left = null;
    resNode = root;
    dsf(root.right)
  }
  dsf(root)
  return dummyNode.right;
};

实现 Trie (前缀树)

js
class Trie {
  constructor() {
    this.children = {}
  }

  insert(word) {
    let node = this.children
    for(let ch of word) {
      if(!node[ch]) {
        node[ch] = {}
      }
      node = node[ch]
    }
    node.isEnd = true
  }

  searchPrefix(word) {
    let node = this.children
    for(let ch of word) {
      if(!node[ch]) {
        return false
      }
      node = node[ch]
    }
    return node
  }
  
  search(word) {
    const node = this.searchPrefix(word)
    return !!node && !!node.isEnd;
  }

  startsWith(prefix) {
    return this.searchPrefix(prefix) 
  }
}

二叉树的最近公共祖先

js
var lowestCommonAncestor = function(root, p, q) {
  let ans;
  const dfs = (root, p, q) => {
    if (root === null) return false;
    const lson = dfs(root.left, p, q);
    const rson = dfs(root.right, p, q);
    if ((lson && rson) || ((root.val === p.val || root.val === q.val) && (lson || rson))) {
      ans = root;
    }
    return lson || rson || (root.val === p.val || root.val === q.val);
  }
  dfs(root, p, q);
  return ans;
};

Released under the MIT License.