Skip to content

二叉搜索树

不同的二叉搜索树

ts
function numTrees(n: number): number {
  const dp = new Array<number>(n + 1).fill(0);
  dp[0] = 1;
  for (let i = 1; i <= n; ++i) {
    for (let j = 0; j < i; ++j) {
      dp[i] += dp[j] * dp[i - j - 1];
    }
  }
  return dp[n];
}

验证二叉搜索树

ts
function isValidBST(root: TreeNode | null): boolean {
  const dfs = (
    root: TreeNode | null,
    minVal: number,
    maxVal: number
  ): boolean => {
    if (!root) {
      return true;
    }
    if (root.val <= minVal || root.val >= maxVal) {
      return false;
    }
    return (
      dfs(root.left, minVal, Math.min(maxVal, root.val)) &&
      dfs(root.right, Math.max(minVal, root.val), maxVal)
    );
  };
  return dfs(root, -Infinity, Infinity);
}

把二叉搜索树转换为累加树

  • 递归
ts
function convertBST(root: TreeNode | null): TreeNode | null {
  let sum = 0;

  const reverseInorder = (root: TreeNode | null): void => {
    if (root) {
      reverseInorder(root.right);
      sum += root.val;
      root.val = sum;
      reverseInorder(root.left);
    }
  };

  reverseInorder(root);
  return root;
}
  • 迭代
ts
function convertBST(root: TreeNode | null): TreeNode | null {
  const stack: TreeNode[] = [];
  let curr = root;
  let sum = 0;
  while (curr || stack.length) {
    while (curr) {
      stack.push(curr);
      curr = curr.right;
    }
    curr = stack.pop();
    sum += curr.val;
    curr.val = sum;
    curr = curr.left;
  }
  return root;
}

二叉搜索树中第 K 小的元素

ts
class TopKBst {
  private root: TreeNode | null = null;
  private nodeNumMap = new Map<TreeNode, number>();

  constructor(root: TreeNode | null) {
    this.root = root;
    this.countNodeNum(root);
  }

  kthSmallest(k: number): number {
    let curr = this.root;
    while (curr) {
      const leftNodeNum = this.getNodeNum(curr.left);
      if (k - 1 === leftNodeNum) {
        return curr.val;
      } else if (k - 1 < leftNodeNum) {
        curr = curr.left;
      } else {
        k -= leftNodeNum + 1;
        curr = curr.right;
      }
    }
    return -1;
  }

  private countNodeNum(root: TreeNode | null): number {
    if (!root) {
      return 0;
    }
    const nodeNum =
      1 + this.countNodeNum(root.left) + this.countNodeNum(root.right);
    this.nodeNumMap.set(root, nodeNum);
    return nodeNum;
  }

  private getNodeNum(root: TreeNode | null): number {
    return this.nodeNumMap.get(root) ?? 0;
  }
}

function kthSmallest(root: TreeNode | null, k: number): number {
  const bst = new TopKBst(root);
  return bst.kthSmallest(k);
}

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

js
function lowestCommonAncestor(root, p, q) {
  let res = undefined;

  const dfs = root => {
    if (res || !root) {
      return [false, false];
    }
    let [leftHasP, leftHasQ] = [false, false];
    let [rightHasP, rightHasQ] = [false, false];
    if (root.val < p.val && root.val < q.val) {
      [rightHasP, rightHasQ] = dfs(root.right);
    } else if (p.val < root.val && q.val < root.val) {
      [leftHasP, leftHasQ] = dfs(root.left);
    } else {
      [leftHasP, leftHasQ] = dfs(root.left);
      [rightHasP, rightHasQ] = dfs(root.right);
    }
    const hasP = root === p || leftHasP || rightHasP;
    const hasQ = root === q || leftHasQ || rightHasQ;
    if (!res && hasP && hasQ) {
      res = root;
    }
    return [hasP, hasQ];
  };

  dfs(root);
  return res;
}