js-BigInt-算法场景运用

38 阅读2分钟

虽然我们知道js中的精度,范围在-2^53 --- 2^53 次方,正常数值计算不会超,但是这次遇到一个算法题,需要给满二叉树标记序号,由于满二叉树每层的数会以 2^n次方, 会出现指数级别增长.当层数超过53 层,直接爆. 联想到 js有bigInt

662. 二叉树最大宽度

给你一棵二叉树的根节点 root ,返回树的 最大宽度 。

树的 最大宽度 是所有层中最大的 宽度 。

每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。

题目数据保证答案将会在  32 位 带符号整数范围内。

示例 1:

输入: root = [1,3,2,5,3,null,9]
输出: 4
解释: 最大宽度出现在树的第 3 层,宽度为 4 (5,3,null,9) 。

示例 2:

输入: root = [1,3,2,5,null,null,9,6,null,7]
输出: 7
解释: 最大宽度出现在树的第 4 层,宽度为 7 (6,null,null,null,null,null,7) 。
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var widthOfBinaryTree = function (root) {
  class TreeId {
    constructor(node, id) {
      this.node = node;
      this.id = BigInt(id);
    }
  }
  if (root === null) {
    return 0;
  }
  let maxLen = BigInt(0)
  let queue = [new TreeId(root, BigInt(1))];

  while (queue.length > 0) {
    let len = queue.length
    //为什么放在循环外
    let left = queue[0].id
    //这里没有理解
    let right = queue[len - 1].id;
    // 计算当前层的宽度并更新最大宽度
    maxLen = maxLen > (right - left + BigInt(1)) ? maxLen : (right - left + BigInt(1));
    // 大整数无法用Math.max
    // maxLen = Math.max(maxLen, right - left + 1);
    while (len > 0) {

      let target = queue.shift();
      let curId = target.id;

      if (target?.node?.left) {
        queue.push(new TreeId(target.node.left, (curId * BigInt(2))))
      }
      if (target?.node?.right) {
        queue.push(new TreeId(target.node.right, (curId * BigInt(2) + BigInt(1))))
      }
      len--
    }

  }

  return Number(maxLen)
};

对于可能出现超精度的数组计算可以利用 BigInt来灵活处理 可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数 BigInt()(但不包含 new 运算符)并传递一个整数值或字符串值,不能用Math方法